From 8bfcf43c18196b83fdefd4c75a88888c00eb8833 Mon Sep 17 00:00:00 2001 From: ananthakumaran Date: Sat, 13 Jan 2024 18:12:50 +0000 Subject: [PATCH] =?UTF-8?q?Deploying=20to=20gh-pages=20from=20@=20ananthak?= =?UTF-8?q?umaran/paisa@67d7658856676f19510df0e2dedbb545907c22be=20?= =?UTF-8?q?=F0=9F=9A=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lexer/__pycache__/hook.cpython-311.pyc | Bin 1776 -> 1776 bytes manifesto/index.html | 10 +++++----- search/search_index.json | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lexer/__pycache__/hook.cpython-311.pyc b/lexer/__pycache__/hook.cpython-311.pyc index 55d98637aa26d443677205e802308473e6920736..10e5ca5283178db4daa01761c50b26e2babd6c2e 100644 GIT binary patch delta 19 Zcmeys`+=8hIWI340}!NN+Q{{c4FEbY1+V}B delta 19 Zcmeys`+=8hIWI340}!}g*vR#a4FEY>1&jay diff --git a/manifesto/index.html b/manifesto/index.html index c47dd4ea..2142b824 100644 --- a/manifesto/index.html +++ b/manifesto/index.html @@ -1627,7 +1627,7 @@

1. Data Ownership Ledger text format is used to store all the transaction data

+

Ledger text format is used to store all the transaction data.

2. Privacy

User's data is private. Paisa will not collect or send any data to any @@ -1643,10 +1643,10 @@

3. Longevity
diff --git a/search/search_index.json b/search/search_index.json index ea564414..a765ddb0 100644 --- a/search/search_index.json +++ b/search/search_index.json @@ -1 +1 @@ -{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"]},"docs":[{"location":"","title":"Home","text":"INR USD EURO
2022/01/01 Salary\n    Income:Salary:Acme     -100,000 INR\n    Assets:Checking         100,000 INR\n\n2022/01/03 Rent\n    Assets:Checking         -20,000 INR\n    Expenses:Rent\n\n2022/01/07 Investment\n    Assets:Checking         -20,000 INR\n    Assets:Equity:NIFTY   168.690 NIFTY @ 118.56 INR\n
2022/01/01 Salary\n    Income:Salary:Acme      $-5,000\n    Assets:Checking          $5,000\n\n2022/01/03 Rent\n    Assets:Checking         $-2,000\n    Expenses:Rent\n\n2022/01/07 Investment\n    Assets:Checking         $-1,000\n    Assets:Equity:AAPL   6.452 AAPL @ $154.97\n
commodity \u20ac\n    format \u20ac1.000,00\n\ncommodity AAPL\n    format 1.000,00 AAPL\n\n2022/01/01 Salary\n    Income:Salary:Acme      \u20ac-5.000\n    Assets:Checking          \u20ac5.000\n\n2022/01/03 Rent\n    Assets:Checking         \u20ac-2.000\n    Expenses:Rent\n\n2022/01/07 Investment\n    Assets:Checking      \u20ac-1.000,02\n    Assets:Equity:AAPL   6,453 AAPL @ \u20ac154,97\n

Install Demo

  • Builds on top of the ledger double entry accounting tool.
  • Your financial data never leaves your system.
  • The journal and configuration information are stored in plain text files that can be easily version controlled. You can collaborate with others by giving access to the files.
  • Track the latest market price of your Mutual Fund, NPS Fund and Stock holdings.
  • Track and budget your Expenses.
  • Convert CSV, Excel and PDF files to Ledger journal.
  • Track your goals.
  • View your recurring transactions.
  • Plan your retirement.
  • And many more visualizations to help you make any financial decisions.
"},{"location":"#personal-finance-manager","title":"Personal Finance Manager","text":""},{"location":"faq/","title":"FAQs","text":"

I already use ledger/hledger/beancount. How do I get started?

Go through the installation docs and get the app working. Go to configuration page and update journal_path, ledger_cli, default_currency and locale. At this point you should be able to view your journal data. Read the accounts docs to understand the account naming conventions followed by paisa.

How do I get started?

You have installed paisa and gone through the demo and you like it, but you don't know what to do next. There is no way you would sit and type all the transactions you have made in the last decade or so.

Paisa is an accounting application and you can focus on things that matters to you the most. For example, if you are not interested in tracking expenses, you can just have a single expense transaction per month. You decide the granularity at which you want to record the transactions. Just recording a few transactions per month like your salary, monthly expense and investments will go a long way and will give you pretty good picture of your finances.

Mac Desktop app fails with executable file not found in $PATH error

Mac Desktop apps are usually started with different PATH than what you would normally get in a Terminal app. Paisa does a fallback search in the following folders before throwing the error. Check if your executable binary is in any of the folder listed below, if not, create a symbolic link from one of the folders to your executable binary.

/bin\n/usr/bin\n/usr/local/bin\n/sbin\n/usr/sbin\n/opt/homebrew/bin\n
"},{"location":"manifesto/","title":"Manifesto","text":""},{"location":"manifesto/#1-data-ownership","title":"1. Data Ownership","text":"

User owns the data. It should be possible to migrate all the data to another app or service. Paisa will strive to make this as easy as possible by choosing open standards and formats.

Ledger text format is used to store all the transaction data

"},{"location":"manifesto/#2-privacy","title":"2. Privacy","text":"

User's data is private. Paisa will not collect or send any data to any server1. Paisa will not use any third party analytics or tracking on the app2.

Paisa's source code is open source and could be audited by anyone.

"},{"location":"manifesto/#3-longevity","title":"3. Longevity","text":"

The app should be available for a long time. It takes a lot of effort to collect and maintain the transaction data. The app should not just disappear one day. Paisa will strive to avoid unnecessary dependencies and build a self contained app.

Paisa is licensed under AGPL v3, which helps with this issue to some extent. I have yet to figure out a way to make the app development and maintenance process sustainable in the long term. But rest assured, any decision made related to this will not override the first two points.

  1. Paisa fetches commodity price information from third party servers. Since Paisa will send the commodity identifier to the server, the third party server might be able to connect the commodity list with the user's IP address. This is an opt-in feature, as you have to explicitly configure Paisa to fetch price. VPN could be used if you want to avoid this.\u00a0\u21a9

  2. This doesn't include the website paisa.fyi, which is hosted on third party servers and has consent based analytics.\u00a0\u21a9

"},{"location":"blog/","title":"Blog","text":""},{"location":"blog/2024/01/03/localization/","title":"Localization","text":"

The way numbers are formatted varies across various countries. In this post, I am going to talk about how to configure localization in Paisa so you can use the number formatting you are familiar with.

The User Interface localization is controlled by configuration, and the Journal file localization is controlled by the commodity directive.

"},{"location":"blog/2024/01/03/localization/#user-interface","title":"User Interface","text":""},{"location":"blog/2024/01/03/localization/#locale","title":"locale","text":"

The way the numbers are formatted by the User Interface is controlled by the configuration key called locale. By default, this value is set to en-IN. It can be edited via the configuration page. The value is made of two parts: the first part is the language name, and the second part is the region name. Refer to Wikipedia for the full list of supported language and country codes.

"},{"location":"blog/2024/01/03/localization/#default_currency","title":"default_currency","text":"

Paisa supports multiple currencies, but it needs you to set one of the currencies as the default currency. The User Interface shows all the numbers in the default currency.

"},{"location":"blog/2024/01/03/localization/#display_precision","title":"display_precision","text":"

Paisa also allows you to control the number of digits shown after the decimal point. By default, it's set to zero.

"},{"location":"blog/2024/01/03/localization/#journal","title":"Journal","text":"

In most cases, you don't have to worry about the journal file since you can enter the value in the correct format and the ledger will parse it fine. But if you want to follow European number formatting, then you would have to use commodity directive to declare the number formatting. In the example below, we instruct the ledger to treat , as decimal separator and . as thousand separator.

commodity EUR\n    format 1.000,00 EUR\n\n2024/01/01 Salary\n    Income:Salary:Acme                    -11.000,00 EUR\n    Assets:Checking                        11.000,00 EUR\n
"},{"location":"getting-started/installation/","title":"Installation","text":"

Paisa is available in two formats: a Desktop Application and a CLI (Command Line Interface). Both provide the same list of features, with the primary difference being how the user interface is launched.

"},{"location":"getting-started/installation/#desktop-application","title":"Desktop Application","text":"LinuxMacWindows
  • Download the prebuilt binary named paisa-app-linux-amd64.deb
  • You can install it either by double clicking the deb file or run the following commands in a Terminal
# cd ~/Downloads\n# sudo dpkg -i paisa-app-linux-amd64.deb\n
  • Download the prebuilt binary named paisa-app-macos-amd64.dmg
  • Open the dmg file and drag the Paisa app into Application folder
  • Since the app is not signed1, Mac will show a warning when you try to open the app. You can check the support page for more details. If you don't get any option to open the app, go to the Application folder, right click on the icon and select open. Usually, this should present you with an option to open.
  • Paisa will store all your journals, configuration files, and other related files in a folder named paisa which will be located in your Documents folder. When you open the app on your Mac for the first time, a permission dialog will appear. Click Allow, then close and reopen the app.
  • Download the prebuilt binary named paisa-app-windows-amd64.exe
  • Since the app is not signed1, Windows will show multiple warnings, You might have to click Keep anyway, More info, Run anyway etc.
  • Paisa will store all your journals, configuration files, and other related files in a folder named paisa which will be located in your Documents folder.
"},{"location":"getting-started/installation/#third-party-hosted-options-2","title":"Third Party Hosted Options 2","text":"PikaPods

PikaPods lets you run Paisa on a server with a few clicks. It handles app upgrades, backup and hosting for you. Make sure to setup a user account post installation.

"},{"location":"getting-started/installation/#cli","title":"CLI","text":"LinuxMacWindows
  • Download the prebuilt binary named paisa-cli-linux-amd64
  • Run the following commands in a Terminal
# cd ~/Downloads\n# mv paisa-cli-linux-amd64 paisa\n# chmod u+x paisa\n# mv paisa /usr/local/bin\n
  • Download the prebuilt binary named paisa-cli-macos-amd64
  • Run the following commands in a Terminal
# cd ~/Downloads\n# mv paisa-cli-macos-amd64 paisa\n# chmod u+x paisa\n# xattr -dr com.apple.quarantine paisa\n# mv paisa /usr/local/bin\n
  • Download the prebuilt binary named paisa-cli-windows-amd64.exe
  • Since the binary is not signed1 with a certificate, you might get a warning from Windows. You would have to click keep anyway.
  • Run the following command in a Windows PowerShell. Make sure you are in the correct folder. You should see something like PS C:\\Users\\yourname>
PS C:\\Users\\john> mv .\\Downloads\\paisa-cli-windows-amd64.exe .\\paisa.exe\n
  • The paisa.exe binary will be placed in the user's home directory. You can access it via PowerShell. Just open a new PowerShell window, which will start in the home directory. Then, you can run .\\paisa.exe serve

Tip

Paisa depends on the ledger binary. The prebuilt paisa binaries come with an embedded ledger binary and will use it if it's not already installed on your system. If you prefer to install the ledger yourself, follow the installation instructions on ledger site.

"},{"location":"getting-started/installation/#cli-quick-start","title":"CLI Quick Start","text":"

Paisa will store all your journals, configuration files, and other related files in a folder named paisa which will be located in your Documents folder.

LinuxMacWindows
# paisa serve\n
# paisa serve\n
PS C:\\Users\\john> .\\paisa.exe serve\n

Go to http://localhost:7500. Read the tutorial to learn more.

"},{"location":"getting-started/installation/#docker","title":"Docker","text":"

Paisa CLI is available on dockerhub.

LinuxMac
# mkdir -p /home/john/Documents/paisa/\n# docker run -p 7500:7500 -v /home/john/Documents/paisa/:/root/Documents/paisa/ ananthakumaran/paisa:latest\n
# mkdir -p /Users/john/Documents/paisa/\n# docker run -p 7500:7500 -v /Users/john/Documents/paisa/:/root/Documents/paisa/ ananthakumaran/paisa:latest\n
"},{"location":"getting-started/installation/#nix-flake","title":"Nix Flake","text":"

Paisa CLI is available as a nix flake.

LinuxMac
# nix profile install github:ananthakumaran/paisa\n
# nix profile install github:ananthakumaran/paisa\n
  1. I offer Paisa as a free app, and I don't generate any revenue from it. Code signing would require me to pay $99 for Mac and approximately $300 for Windows each and every year to get the necessary certificates. I can't justify spending that much for an app that doesn't generate any income. Unfortunately, as a result, you would have to jump through hoops to get it working.\u00a0\u21a9\u21a9\u21a9

  2. As the name implies, these are third party hosting solutions operated by independent companies. I may receive affiliate compensation for linking to their websites.\u00a0\u21a9

"},{"location":"getting-started/tutorial/","title":"Tutorial","text":"

This tutorial will introduce all the concepts necessary to get started. Paisa builds on top of the ledger1, a command line tool that follows the principles of plain text accounting. ledger primarily focuses on command line users and doesn't provide any graphical user interface. Paisa aims to create a low-friction graphical user interface on top of ledger, thereby making it accessible to a wider range of users.

As an end user, you should be familiar with the terms and concepts used by ledger, which we will cover below. Paisa comes with an embedded ledger and you are not required to use ledger via command line unless you want to.

Tip

Even though the tutorial focuses on Indian users, Paisa is capable of handling any currency. You can change the default currency, locale and financial year starting month etc. Check the configuration reference for more details.

"},{"location":"getting-started/tutorial/#journal","title":"Journal","text":"

A journal file captures all your financial transactions. A transaction may represent a mutual fund purchase, retirement contribution, grocery purchase and so on. Paisa creates a journal named main.ledger, Let's add our first transaction there. To open the editor, go to Ledger Editor

2022/01/01/*(1)!*/ Salary/*(2)!*/\n    Income:Salary:Acme/*(3)!*/   -100,000 INR/*(6)!*/\n    Assets:Checking/*(4)!*/    /*(5)!*/100,000 INR\n
  1. Transaction Date
  2. Transaction description, also called as Payee
  3. Debit Account
  4. Credit Account
  5. Amount
  6. Currency

ledger follows the double-entry accounting system. In simple terms, it tracks the movement of money from debit account to credit account. Here Income:Salary:Acme is the debit account and Assets:Checking is the credit account. The date at which the transaction took place and a description of the transaction is written in the first line followed by the list of credit or debit entry. Account naming conventions are explained later. The : in the account name represents hierarchy.

2022/01/01 Salary\n    Income:Salary:Acme      -100,000 INR\n    Assets:Checking          100,000 INR\n\n2022/02/01 Salary\n    Income:Salary:Acme      -100,000 INR\n    Assets:Checking          100,000 INR\n\n2022/03/01 Salary\n    Income:Salary:Acme      -100,000 INR\n    Assets:Checking          100,000 INR\n

Let's add few more transactions. As you edit your journal file, the balance of the journal will be shown on the right hand side.

         300,000 INR  Assets:Checking\n        -300,000 INR  Income:Salary:Acme\n--------------------\n                   0\n

You would notice zero balance and a checking account with 3 lakhs and an income account with -3 lakhs. Double-entry accounting will always results in 0 balance since you have to always enter both the credit and debit side.

Let's say your company deducts 12,000 INR and contributes it to EPF, we could represent it as follows

2022/01/01 Salary\n    Income:Salary:Acme    -100,000 INR\n    Assets:Checking         88,000 INR\n    Assets:Debt:EPF         12,000 INR\n\n2022/02/01 Salary\n    Income:Salary:Acme    -100,000 INR\n    Assets:Checking         88,000 INR\n    Assets:Debt:EPF         12,000 INR\n\n2022/03/01 Salary\n    Income:Salary:Acme    -100,000 INR\n    Assets:Checking         88,000 INR\n    Assets:Debt:EPF         12,000 INR\n

You can now see the use of : hierarchy in the account name.

         300,000 INR  Assets\n         264,000 INR    Checking\n          36,000 INR    Debt:EPF\n        -300,000 INR  Income:Salary:Acme\n--------------------\n                   0\n
"},{"location":"getting-started/tutorial/#commodity","title":"Commodity","text":"

So far we have only dealt with INR. ledger can handle commodity as well. Let's say you are also investing 10,000 INR in UTI Nifty Index Fund and 10,000 INR in ICICI Nifty Next 50 Index Fund every month.

2018/01/01 Investment\n    Assets:Checking               -20,000 INR\n    Assets:Equity:NIFTY        148.0865 NIFTY @ 67.5281 INR\n    Assets:Equity:NIFTY_JR  358.6659 NIFTY_JR @ 27.8811 INR\n\n2018/02/01 Investment\n    Assets:Checking               -20,000 INR\n    Assets:Equity:NIFTY        140.2870 NIFTY @ 71.2824 INR\n    Assets:Equity:NIFTY_JR  363.2242 NIFTY_JR @ 27.5312 INR\n\n2018/03/01 Withdrawal\n    Assets:Checking                          6775.49 INR\n    Income:CapitalGains:Equity:NIFTY          -22.68 INR\n    Assets:Equity:NIFTY          -100 NIFTY {67.5281 INR} [2018/01/01] @ 67.7549 INR\n

Let's consider 148.0865 NIFTY @ 67.5281 INR. Here NIFTY is the name of the commodity and we have bought 148.0865 units at 67.5281 INR per unit.

The withdrawal transaction is bit more involved. When you buy a commodity, you buy them at a specific price on a specific date called lot. When you sell, you usually need to record which lot you are selling for taxation purpose, usually FIFO. -100 NIFTY {67.5281 INR} [2018/01/01] @ 67.7549 INR means you are selling NIFTY at price 67.7549 INR that was bought on 2018/01/01 at 67.5281 INR. The gain or loss amount comes from the capital gains account Income:CapitalGains:Equity:NIFTY

Paisa has support for fetching commodity price history from few providers. Go to Configuration page and expand the Commodities section. You can click the icon to add a new one. Edit the name to NIFTY. Click the icon near Price section and select the price provider details. Once done, save the configuration and click the Update Prices from the top right hand side menu. If you had done everything correctly, you would see the latest price of the commodity under Assets Balance

"},{"location":"getting-started/tutorial/#interest","title":"Interest","text":"

There are many instruments like EPF, FD, etc that pay interest at regular intervals. We can treat it as just another transaction. Any income account that has a prefix Income:Interest: can be used as the debit account. It's not mandatory to specify the amount at bot side. If you leave one side, ledger will deduct it.

2022/03/31 EPF Interest\n    Income:Interest:EPF     -5,000 INR\n    Assets:Debt:EPF\n
           5,000 INR  Assets:Debt:EPF\n          -5,000 INR  Income:Interest:EPF\n--------------------\n                   0\n
"},{"location":"getting-started/tutorial/#configuration","title":"Configuration","text":"

All the configuration related to paisa is stored in a yaml file named paisa.yaml. The configuration can be edited via the web interface. The sequence in which it looks for the file is described below

  1. PAISA_CONFIG environment variable
  2. via --config flag
  3. Current working directory
  4. paisa/paisa.yaml file inside User Documents folder.

If it can't find the configuration file, it will create a default configuration file named paisa/paisa.yaml inside User Documents folder. The default configuration is tuned for Indians, users from other countries would have to change the default_currency and locale. Check the configuration reference for details.

"},{"location":"getting-started/tutorial/#update","title":"Update","text":"

Paisa fetches the latest price of the commodities only when update command is used. Make sure to run paisa update command after you make any changes to your journal file or you want to fetch the latest value of the commodities. The update can be performed from the UI as well via the dropdown in the top right hand side corner.

  1. hledger and beancount are also supported, refer Ledger CLI for more information.\u00a0\u21a9

"},{"location":"reference/accounts/","title":"Accounts","text":"

If you take a typical transaction, money moves between two parties. In ledger, you call them Account. At least two accounts are involved in any transaction. Accounts are also hierarchical. This helps with the organization. For example you can treat EPF and PPF as two accounts namely Assets:Debt:EPF and Assets:Debt:PPF. The hierarchy helps you ask questions like what is the balance of Assets:Debt, which will include both EPF and PPF.

Even though ledger doesn't have any strict Account naming convention, Paisa expects you to follow the standard naming convention.

There are five types of account namely

  1. Assets
  2. Liabilities
  3. Income
  4. Expenses
  5. Equity

All the accounts you create should be under one of these accounts. This naming convention is a necessity, because without which, it's not possible to tell whether you are spending money or investing money. A transaction from Assets account to Expenses account implies that you are spending money.

Money typically flows from Income to Assets, from Assets to either Expenses, Liabilities or other Assets, from Liabilities to Expenses.

graph LR\n  I[Income] --> A[Assets];\n  A --> E[Expenses];\n  A --> A;\n  A --> L[Liabilities];\n  L --> E[Expenses];

As a general principle, try not to create too many accounts at second level. The UI works best when you create less than or equal to 12 second level accounts under each type. For example, you can have 12 accounts under Expenses. But if you want more, try to add them under 3rd level, example Expenses:Food:Subway.

"},{"location":"reference/accounts/#assets","title":"Assets","text":"

All your assets should go under Assets:. The level of granularity is up to you. The recommended convention is to use Assets:{instrument_type}:{instrument_name}. The instrument type may be Cash, Equity, Debt, etc. The instrument name may be the name of the fund, stock, etc

"},{"location":"reference/accounts/#checking","title":"Checking","text":"

Assets:Checking is a special account where you keep your money for daily use. This will be included in your net worth, but will not be treated as an investment. So gain page for example, will exclude this account and won't show the returns. If you have multiple checking accounts, you can use sub accounts as well, for example Assets:Checking:HDFC and Assets:Checking:AXIS.

The distinction is necessary because Checking account is an asset, but not an investment. So you ideally you want to disregard them when you calculate your absolute returns etc.

"},{"location":"reference/accounts/#income","title":"Income","text":"

All your income should come from Income:. The typical way is to treat each employer as a separate account like Income:Salary:{company}

"},{"location":"reference/accounts/#interest","title":"Interest","text":"

Income:Interest is a special type of account from the perspective of returns calculation. Let's assume you have bought APPLE stock. You might be buying them at regular intervals. To calculate your returns, we can compute the difference between purchase price and current price.

Now in case of FD, you will get your interest credited to your account. The returns is the difference between the amount you deposited and the final balance. It's essential we need to know which transactions are deposits and which are interest credits.

Any money that comes from the sub account of Income:Interest will be treated as interest. This convention allows paisa to calculate the returns of any debt instrument without explicitly specifying anything else.

  • Income:Interest:{name} - interest debit account
"},{"location":"reference/accounts/#capital-gains","title":"Capital Gains","text":"
2018/03/01 Withdrawal\n    Assets:Checking                  6775.49 INR\n    Income:CapitalGains:Equity:NIFTY  -22.68 INR\n    Assets:Equity:NIFTY               -100 NIFTY {67.5281 INR} [2018/01/01] @ 67.7549 INR\n

Let's say you have an asset account named Assets:{name} and you make some profit when you sell the asset, this profit should come from capital gains account named Income:CapitalGains:{name}.

"},{"location":"reference/accounts/#expenses","title":"Expenses","text":"

All your expenses should go to Expenses:{category} accounts. You can also have more than 2 levels as well. The expense page will roll it up to 2 level wherever necessary.

"},{"location":"reference/accounts/#tax","title":"Tax","text":"

Income tax paid to government should be credited to Expenses:Tax account. This is used to calculate your Net Income and your Savings Rate. If you want to track different types of taxes, you can use sub accounts as well, for example Expenses:Tax:Income and Expenses:Tax:GST.

"},{"location":"reference/accounts/#equity","title":"Equity","text":"

Equity is used in rare cases where you want to balance the transaction, but none of the other accounts are suitable for the purpose. Let's say you have 1000 INR in your real bank account and you want your checking account in Paisa to have same balance, you can use Equity account to balance the transaction.

2022/01/01 Opening Balance\n    Assets:Checking:SBI       1000 INR\n    Equity:OpeningBalance\n
"},{"location":"reference/accounts/#icons","title":"Icons","text":"

Each account is associated with an icon and is shown along with the account name in most places. Paisa assigns icon based on few simple rules and it usually falls back to a generic icon. To modify the icon, go to the configuration page, add a new Account and specify the name of your account and then select icon of your choice. Paisa ships with four icon sets.

  • Arcticons
  • Font Awesome Regular, Solid and Brands
  • Material Design Icons
  • Fluent Emoji High Contrast

Experimental

There is a wide range of free icons available, but adding each icon set to Paisa would increase the app binary size. So a balance has to be struck between the number of icons and the app size. Feel free to start a discussion if you feel strongly about any icon set. The current icon sets are not final, they may be replaced if a better alternative is found.

"},{"location":"reference/allocation-targets/","title":"Allocation Targets","text":"

Paisa allows you to set a allocation target for a group of accounts which might represent your assets like mutual funds, stocks etc. The allocation page shows how far your current allocation is from the allocation target. For example, to keep a 40:60 split between debt and equity, use the following configuration. The account name can have * which matches any characters

allocation_targets:\n  - name: Debt\n    target: 40\n    accounts:\n      - Assets:Debt:*\n  - name: Equity\n    target: 60\n    accounts:\n      - Assets:Equity:*\n
"},{"location":"reference/analysis/","title":"Analysis","text":"

Ledger represents everything except currency as commodities. A commodity could represent physical object like Gold or certificates like Stock, Bond etc. Some commodities like Mutual Fund is a container for Securities. When you own a mutual fund unit, you indirectly own these securities.

The Analysis page unwraps the container and shows you what securities you own along with their amount and percentage. It also categorizes the securities by their industry and rating.

Experimental

The data that powers this page comes from various sources and might not be 100% accurate. Before you make any decision based on this information, double check via different source.

"},{"location":"reference/budget/","title":"Budget","text":"

Paisa supports a simple budgeting system. Let's say you get 50000 INR at the beginning of the month. You want to budget this amount and figure out how much you can spend on each category.

Let's add a salary transaction to the ledger:

2023/08/01 Salary\n    Income:Salary:Acme         -50,000 INR\n    Assets:Checking\n

Now you have 50k in your checking account. Let's budget this amount:

~ Monthly in 2023/08/01\n    Expenses:Rent               15,000 INR\n    Expenses:Food               10,000 INR\n    Expenses:Clothing            5,000 INR\n    Expenses:Entertainment       5,000 INR\n    Expenses:Transport           5,000 INR\n    Expenses:Personal            5,000 INR\n    Assets:Checking\n

The ~ character indicates that this is a periodic transaction. This is not a real transaction, but used only for forecasting purposes. You can read more about periodic expressions and periodic transactions.

Bug

Even though the interval part is optional as per the doc, there is a bug in the ledger-cli, so you can't use ~ in 2023/08/01, instead you always have to specify some interval like ~ Monthly in 2023/08/01.

Now you can see that you will have 5k left in your checking account at the end of the month, if you spend as per your budget. Before you spend, you can check your budget and verify if you have money available under that category.

Let's add some real transactions.

2023/08/02 Rent\n    Expenses:Rent               15,000 INR\n    Assets:Checking\n\n2023/08/03 Transport\n    Expenses:Transport           1,000 INR\n    Assets:Checking\n\n2023/08/03 Food\n    Expenses:Food                8,500 INR\n    Assets:Checking\n\n2023/08/05 Transport\n    Expenses:Transport           2,000 INR\n    Assets:Checking\n\n2023/08/07 Transport\n    Expenses:Transport           3,000 INR\n    Assets:Checking\n\n2023/08/10 Personal\n    Expenses:Personal            4,000 INR\n    Assets:Checking\n\n2023/08/15 Insurance\n    Expenses:Insurance           10000 INR\n    Assets:Checking\n

As the month progresses, you can see how much you have spent and how much you have left. You notice that you have overspent on transport and you have missed the insurance payment. You have a budget deficit now. That means, you can't actually spend as per your budget. You have to first bring the deficit back to 0. Let's cut down the entertainment and clothing budget to 0

~ Monthly in 2023/08/01\n    Expenses:Rent              15,000 INR\n    Expenses:Food              10,000 INR\n    Expenses:Clothing               0 INR\n    Expenses:Entertainment          0 INR\n    Expenses:Transport          5,000 INR\n    Expenses:Personal           5,000 INR\n    Assets:Checking\n

You can go back and adjust your budget anytime. Let's move on to the next month, assuming you haven't made any further transaction.

2023/09/01 Salary\n    Income:Salary:Acme        -50,000 INR\n    Assets:Checking\n\n~ Monthly in 2023/09/01\n    Expenses:Rent              15,000 INR\n    Expenses:Food              10,000 INR\n    Expenses:Clothing           5,000 INR\n    Expenses:Entertainment      5,000 INR\n    Expenses:Transport          5,000 INR\n    Expenses:Personal           5,000 INR\n    Assets:Checking\n

You can see a new element in the UI called Rollover1. This is basically the amount you have budgeted last month, but haven't spent. This will automatically rollover to the next month. That's pretty much it.

To recap, there are just two things you need to do.

1) Create a periodic transaction at the beginning of the month when you get your salary.

2) Adjust your budget as you spend and make sure there is no deficit.

  1. If you prefer to not have rollover feature, it can be disabled in the configuration page.\u00a0\u21a9

"},{"location":"reference/bulk-edit/","title":"Bulk Edit","text":"

Paisa provides bulk transaction editor to search and modify multiple transactions at once. The interface is made of two parts:

1) Search input box allows you to narrow down the transactions you are interested in making changes

2) Bulk Edit form allows you to make changes to the narrowed down set of transactions.

"},{"location":"reference/bulk-edit/#search","title":"Search","text":""},{"location":"reference/bulk-edit/#plain","title":"Plain","text":"

Paisa provides a powerful search query interface. Let's start with a few example queries.

Expenses:Utilities:Electricity\n

This will search for all transactions that have a posting with account named Expenses:Utilities:Electricity. By default, the search is case insensitive and will do a substring match. So, Expenses:Utilities will match Expenses:Utilities:Electricity account as well. If you want to search an account name which has special characters like space in it, you can use double quotes to enclose it like \"Expenses:Utilities:Hair Cut\".

You can also search on transaction date. For example, if you want to show all the transactions made on 1st Jan 2023, just type [2023-01-01]. If you want to see all made on that month, just leave out the day part [2023-01]. You can do the same with year, [2023] will show all the transactions made in 2023.

There is experimental support for natural language date. You can do queries like [last month], [last year], [this month], [lastweek], [jan 2023], etc.

Let's say you want to search by amount. You can do that by typing 42, it will show all the transactions that have a posting with that amount.

if you want to search a exact Account, you can do that using Regular Expression. Just type /^Assets:Equity:APPLE$/, you can also do case insensitive search by using the modifier i like /^Assets:Equity:APPLE$/i.

"},{"location":"reference/bulk-edit/#property","title":"Property","text":"

You can also search based on properties like account, commodity, amount, total, filename, note, payee and date.

payee =~ /uber/i\npayee = \"Advance Tax\"\ncommodity = GOLD\ntotal > 5000\nnote = \"rebate\"\naccount = \"Expenses:Utilities:Electricity\"\ndate >= [2023-01-01]\nfilename = creditcard/2023/jan.ledger\n

The general format is property operator value. The property can be any of the following:

  • account - posting account
  • commodity - posting commodity
  • amount - posting amount
  • total - transaction total
  • filename - name of the file the transaction is in
  • note - posting or transaction note (comment)
  • payee - transaction payee
  • date - transaction date

The operator can be any of the following:

  • = equal
  • =~ regular expression match
  • < less than
  • <= less than or equal
  • > greater than
  • >= greater than or equal

Not all the combinations of property, operator and value would work, if in doubt, just try it out, the UI will show you an error if the query is not valid.

In fact, in the previous format we saw, if the property and operator is not specified and a default set is chosen based on the value type. For example, 42 will be treated as amount = 42, Expenses:Utilities will be treated as account = Expenses:Utilities, /Expenses:Utilities/i will be treated as account =~ /Expenses:Utilities/i, [2023-01] will be treated as date = [2023-01].

"},{"location":"reference/bulk-edit/#conditional","title":"Conditional","text":"

You can combine multiple property based queries using AND and OR, you can negate them using NOT

account = Expenses:Utilities AND payee =~ /uber/i\ncommodity = GOLD OR total > 5000\ndate >= [2023-01-01] AND date < [2023-04-01]\naccount = Expenses:Utilities AND payee =~ /uber/i AND (total > 5000 OR total < 1000)\n[last year] AND (payee =~ /swiggy/i OR payee =~ /phonepe/i)\ntotal < 5000 AND NOT account = Expenses:Utilities\n

If you leave out the conditional operator, it will be treated as AND. Both of the below queries are the same

account = Expenses:Utilities payee =~ /uber/i\naccount = Expenses:Utilities AND payee =~ /uber/i\n
"},{"location":"reference/bulk-edit/#bulk-edit-form","title":"Bulk Edit Form","text":"

Currently bulk edit form supports only account rename feature. More will be added later. The preview button allows you to see the changes before you save them. It will show a side by side diff of the changes.

"},{"location":"reference/changelog/","title":"Release Changelog","text":""},{"location":"reference/changelog/#063-2024-01-13","title":"0.6.3 (2024-01-13)","text":"
  • Introduce Sheets: A notepad calculator with access to your ledger
  • Remove flat option from cashflow > yearly page
  • Dockerimage now installs paisa to /usr/bin
  • Improve legends rendering on all pages
  • Allow user to cancel pdf password prompt
  • Add new warning for missing assets accounts from allocation target
  • Support hledger's balance assertion
  • Bug fixes
"},{"location":"reference/changelog/#062-2023-12-23","title":"0.6.2 (2023-12-23)","text":"
  • New logo
  • Allow goals to be reordered
  • Show goals on the dashboard page
  • Bug fixes
"},{"location":"reference/changelog/#061-2023-12-16","title":"0.6.1 (2023-12-16)","text":"
  • Add new price provider: Alpha Vantage
  • Make first day of the week configurable
  • Support ledger strict mode
  • Add user login support, go to User Accounts section in configuration page to enable it
  • Show notes associated with a transaction/posting
  • Bug fixes
"},{"location":"reference/changelog/#060-2023-12-09","title":"0.6.0 (2023-12-09)","text":"
  • Add individual account balance on goals page
  • Add keyboard shortcuts to format/save file on editor page
  • Add ability to search posting/transaction by note
  • Add option to reverse the order of generated transactions on import page
  • Add option to clear price cache
  • Bug fixes
"},{"location":"reference/changelog/#059-2023-11-26","title":"0.5.9 (2023-11-26)","text":"
  • Improve postings page
  • Add income statement page (Cash Flow > Income Statement)
  • Bug fixes
"},{"location":"reference/changelog/#058-2023-11-18","title":"0.5.8 (2023-11-18)","text":"
  • Add ability to specify rate, target date or monthly contribution to savings goal
  • Improve price page
  • Bug fixes
"},{"location":"reference/changelog/#057-2023-11-11","title":"0.5.7 (2023-11-11)","text":"
  • Add goals
  • Remove retirement page (available under goals)
  • Bug fixes
"},{"location":"reference/changelog/#breaking-changes","title":"Breaking Changes","text":"

Retirement page has been moved under goals. If you have used retirement, you need to setup a new retirement goal

"},{"location":"reference/changelog/#056-2023-11-04","title":"0.5.6 (2023-11-04)","text":"
  • Add support for Income:CapitalGains
  • Add option to control display precision
  • Add new price provider for gold and silver (IBJA India)
  • Add option to disable budget rollover
  • Bug fixes
"},{"location":"reference/changelog/#055-2023-10-07","title":"0.5.5 (2023-10-07)","text":"
  • Support account icon customization
  • Add beancount ledger client support
"},{"location":"reference/changelog/#054-2023-10-07","title":"0.5.4 (2023-10-07)","text":"
  • Add calendar view to recurring page
  • Support recurring period configuration
  • Support European number format
  • Bug fixes
"},{"location":"reference/changelog/#053-2023-09-30","title":"0.5.3 (2023-09-30)","text":"
  • Add Docker Image
  • Add Linux Application (deb package)
  • Move import templates to configuration file
  • Bug fixes
"},{"location":"reference/changelog/#breaking-changes_1","title":"Breaking Changes","text":"

User's custom import templates used to be stored in Database, which is a bad idea in hindsight. It's being moved to the configuration file. With this change, all the data in paisa.db would be transient and can be deleted and re created from the journal and configuration files without any data loss.

If you have custom template, take a backup before you upgrade and add it again via new version. If you have already upgraded, you can still get the data directly from the db file using the following query sqlite3 paisa.db \"select * from templates\";

"},{"location":"reference/changelog/#052-2023-09-22","title":"0.5.2 (2023-09-22)","text":"
  • Add Desktop app
  • Support password protected PDF on import page
  • Bug fixes
"},{"location":"reference/changelog/#breaking-changes_2","title":"Breaking Changes","text":"
  • The structure of price code configuration has been updated to make it easier to add more price provider in the future. In addition to the code, the provider name also has to be added. Refer the config documentation for more details
     type: mutualfund\n-    code: 122639\n+    price:\n+      provider: in-mfapi\n+      code: 122639\n     harvest: 365\n
"},{"location":"reference/changelog/#050-2023-09-16","title":"0.5.0 (2023-09-16)","text":"
  • Add config page
  • Embed ledger binary inside paisa
  • Bug fixes
"},{"location":"reference/changelog/#049-2023-09-09","title":"0.4.9 (2023-09-09)","text":"
  • Add search query support in transaction page
  • Spends at child accounts level would be included in the budget of parent account.
  • Fix the windows build, which was broken by the recent changes to ledger import
  • Bug fixes
"},{"location":"reference/changelog/#048-2023-09-01","title":"0.4.8 (2023-09-01)","text":"
  • Add budget
  • Add hierarchial cash flow
  • Switch from float64 to decimal
  • Bug fixes
"},{"location":"reference/changelog/#047-2023-08-19","title":"0.4.7 (2023-08-19)","text":"
  • Add dark mode
  • Add bulk transaction editor
"},{"location":"reference/commodities/","title":"Commodities","text":"

There are no restrictions on the type of commodities that can be used in Paisa. Anything like gold, mutual fund, NPS, etc can be tracked as a commodity. Few example transactions can be found below.

2019/02/18 NPS\n    Assets:Equity:NPS:SBI:E/*(1)!*/  /*(2)!*/15.9378 NPS_SBI_E/*(3)!*/ @ /*(4)!*/23.5289 INR/*(5)!*/\n    Assets:Checking\n\n2019/02/21 NPS\n    Assets:Equity:NPS:SBI:E      1557.2175 NPS_SBI_E @ 23.8406 INR\n    Assets:Checking\n\n2020/06/25 Gold\n    Assets:Gold                         40 GOLD @ 4650 INR\n    Assets:Checking\n
  1. Account name
  2. Number of units purchased
  3. Commodity Name
  4. Purchase Price per Unit
  5. Currency

Paisa comes with inbuilt support for fetching the latest price of some commodities like mutual fund, NPS, stocks, etc from few providers. For others, it will try to use the latest purchase price specified in the journal. For example, when you enter the second NPS transaction on 2019/02/21, the valuation of your existing holdings will be adjusted based on the new purchase price.

To link a commodity with a commodity price provider, Go to Configuration page and expand the Commodities section. You can click the icon to add a new one. Edit the name to commodity name. Click the icon near Price section and select the price provider details. Once done, save the configuration and click the Update Prices from the top right hand side menu. If you had done everything correctly, you would see the latest price of the commodity under Assets Balance. You can also view the full price history on Ledger Price

"},{"location":"reference/commodities/#mf-api-mutual-fund","title":"MF API Mutual Fund","text":"

To automatically track the latest value of your mutual funds holdings, you need to link the commodity and the fund scheme code.

commodities:\n  - name: NIFTY # (1)!\n    type: mutualfund # (2)!\n    price:\n        provider: in-mfapi # (3)!\n        code: 120716 # (4)!\n
  1. commodity name
  2. commodity type
  3. price provider name
  4. mutual fund scheme code

The example configuration above links nifty commodity with the respective mutual fund scheme code.

"},{"location":"reference/commodities/#yahoo","title":"Yahoo","text":"

To automatically track the latest value of your stock holdings, you need to link the commodity and the stock ticker name.

commodities:\n  - name: APPLE # (1)!\n    type: stock # (2)!\n    price:\n        provider: com-yahoo # (3)!\n        code: AAPL # (4)!\n
  1. commodity name
  2. type
  3. price provider name
  4. stock ticker code

Stock prices are fetched from yahoo finance website. The ticker code should match the code used in yahoo. If the fetched price currency is not the default currency, it will be converted to default currency using the forex rate apis.

"},{"location":"reference/commodities/#alpha-vantage","title":"Alpha Vantage","text":"

Supports 100,000+ stocks, ETFs, mutual funds etc. It also provides exchange rates, so the price can be converted to default currency if required.

commodities:\n  - name: RELIANCE # (1)!\n    type: stock # (2)!\n    price:\n        provider: co-alphavantage # (3)!\n        code: 7GAURDT55LU7OQKK:RELIANCE.BSE:INR # (4)!\n
  1. commodity name
  2. type
  3. price provider name
  4. code

Code is made of three parts, apiKey, symbol and currency. For example in 7GAURDT55LU7OQKK:RELIANCE.BSE:INR, 7GAURDT55LU7OQKK is the api key, RELIANCE.BSE is the symbol and INR is the currency. Alpha Vantage provides free api key with 25 requests per day limit.

"},{"location":"reference/commodities/#purified-bytes-nps","title":"Purified Bytes NPS","text":"

To automatically track the latest value of your nps funds holdings, you need to link the commodity and the fund scheme code.

commodities:\n  - name: NPS_HDFC_E # (1)!\n    type: nps # (2)!\n    price:\n        provider: com-purifiedbytes-nps # (3)!\n        code: SM008002 # (4)!\n
  1. commodity name
  2. type
  3. price provider name
  4. nps fund scheme code

The example configuration above links NPS fund commodity with their respective NPS fund scheme code.

"},{"location":"reference/commodities/#purified-bytes-metals","title":"Purified Bytes Metals","text":"

To automatically track the latest price of gold or silver at various level of purity, you need to link the commodity and the metal code. The price is for 1 gram of the metal.

commodities:\n  - name: GOLD # (1)!\n    type: metal # (2)!\n    price:\n        provider: com-purifiedbytes-metal # (3)!\n        code: gold-999 # (4)!\n
  1. commodity name
  2. type
  3. price provider name
  4. metal name along with purity

The following metals and purity combinations are supported.

Metal Purity Code Gold 999 gold-999 Gold 995 gold-995 Gold 916 gold-916 Gold 750 gold-750 Gold 585 gold-585 Silver 999 silver-999"},{"location":"reference/commodities/#realestate","title":"RealEstate","text":"

Some commodities like real estate are bought once and the price changes over time. Ledger allows you to set the price as on date.

2014/01/01 Home purchase\n    Assets:House                                1 APT @ 4000000 INR\n    Liabilities:Homeloan\n\nP 2016/01/01 00:00:00 APT 5000000 INR\nP 2018/01/01 00:00:00 APT 6500000 INR\nP 2020/01/01 00:00:00 APT 6700000 INR\nP 2021/01/01 00:00:00 APT 6300000 INR\nP 2022/01/01 00:00:00 APT 8000000 INR\n
"},{"location":"reference/commodities/#currencies","title":"Currencies","text":"

If you need to deal with multiple currencies, just treat them as you would treat any commodity. Since paisa is a reporting tool, it will always try to convert other currencies to the default_currency. As long as the exchange rate from a currency to default_currency is available, paisa would work without issue

P 2023/05/01 00:00:00 USD 81.75 INR\n\n2023/05/01 Freelance Income\n    ;; conversion rate will be picked up\n    ;; from the price directive above\n    Income:Freelance      -100 USD\n    Assets:Checking\n\n2023/06/01 Freelance Income\n    ;; conversion rate is specified inline\n    Income:Freelance      -200 USD @ 82.75 INR\n    Assets:Checking\n\n2023/07/01 Netflix\n    ;; if not available for a date,\n    ;; will use previous known conversion rate (82.75)\n    Expenses:Entertainment  10 USD\n    Assets:Checking\n
"},{"location":"reference/commodities/#update","title":"Update","text":"

Paisa fetches the latest price of the commodities only when you update the prices. This can be done via UI using the dropdown in the top right hand side corner or via paisa update command. Make sure to update the prices after you make any changes to your journal file or you want to fetch the latest value of the commodities.

"},{"location":"reference/config/","title":"Configuration","text":"

All the configuration related to paisa is stored in a yaml file named paisa.yaml. The configuration can be edited via the web interface. The sequence in which paisa looks for the file is described below

  1. PAISA_CONFIG environment variable
  2. via --config flag
  3. Current working directory
  4. paisa/paisa.yaml file inside User Documents folder.

If it can't find the configuration file, it will create a default configuration file named paisa/paisa.yaml inside User Documents folder. The default configuration is tuned for Indians, users from other countries would have to change the default_currency and locale.

"},{"location":"reference/config/#accounts","title":"Accounts","text":"

In many places, paisa expects you to specify a list of accounts. You can type the full account name like Account:Equity:APPL. Paisa also supports wildcard *, you can use Account:Equity:* to represent all accounts under Equity. It's also possible to use negation. !Expenses:Tax will match all accounts except Tax. If you use negation, then all the accounts should be negation. Don't mix negation with others, if done the behavior will be undefined.

# Path to your journal file. It can be absolute or relative to the\n# configuration file. The main journal file can refer other files using\n# `include` as long as all the files are in the same or sub directory\n# REQUIRED\njournal_path: /home/john/Documents/paisa/main.ledger\n\n# Path to your database file. It can be absolute or relative to the\n# configuration file. The database file will be created if it does not exist.\n# REQUIRED\ndb_path: /home/john/Documents/paisa/paisa.db\n\n# The ledger client to use\n# OPTIONAL, DEFAULT: ledger, ENUM: ledger, hledger, beancount\nledger_cli: ledger\n\n# The default currency to use. NOTE: Paisa tries to convert other\n# currencies to default currency, so make sure it's possible to\n# convert to default currency by specifying the exchange rate.\n#\n# OPTIONAL, DEFAULT: INR\ndefault_currency: INR\n\n# The locale used to format numbers. The list of locales supported\n# depends on your browser. It's known to work well with en-US and en-IN.\n#\n# OPTIONAL, DEFAULT: en-IN\nlocale: en-IN\n\n# First month of the financial year. This can be set to 1 to follow\n# January to December.\n#\n# OPTIONAL, DEFAULT: 4\nfinancial_year_starting_month: 4\n\n# First day of the week. This can be set to 1 to follow Monday to\n# Sunday. 0 represents Sunday, 1 represents Monday and so on.\n#\n# OPTIONAL, DEFAULT: 0\nweek_starting_day: 0\n\n# When strict mode is enabled, all the accounts and commodities should\n# be defined before use. This is same as --pedantic flag in ledger and\n# --strict flag in hledger. Doesn't apply to beancount.\n#\n# OPTIONAL, ENUM: yes, no DEFAULT: no\nstrict: \"no\"\n\n## Budget\nbudget:\n  # Rollover unspent money to next month\n  # OPTIONAL, ENUM: yes, no DEFAULT: yes\n  rollover: \"yes\"\n\n## Goals\ngoals:\n  # Retirement goals\n  retirement:\n      # Goal name\n      # REQUIRED\n    - name: Retirement\n      # Goal icon\n      # REQUIRED\n      icon: mdi:palm-tree\n      # Safe Withdrawal Rate\n      # OPTIONAL, DEFAULT: 4\n      swr: 2\n      # List of expense accounts\n      # OPTIONAL, DEFAULT: Expenses:*\n      expenses:\n        - Expenses:Clothing\n        - Expenses:Education\n        - Expenses:Entertainment\n        - Expenses:Food\n        - Expenses:Gift\n        - Expenses:Insurance\n        - Expenses:Misc\n        - Expenses:Restaurant\n        - Expenses:Shopping\n        - Expenses:Utilities\n      # List of accounts where you keep retirement savings\n      # OPTIONAL, DEFAULT: Assets:*\n      savings:\n        - Assets:Equity:*\n        - Assets:Debt:*\n      # By default, average of last 3 year expenses will be used to\n      # calculate your yearly expenses. This can be overridden by setting\n      # this configuration to positive value\n      # OPTIONAL, DEFAULT: 0\n      yearly_expenses: 0\n  savings:\n      # Goal name\n      # REQUIRED\n    - name: House\n      # Goal icon\n      # REQUIRED\n      icon: fluent-emoji-high-contrast:house-with-garden\n      # Goal target amount\n      # REQUIRED\n      target: 100000\n      # Goal target date\n      # OPTIONAL (either target_date or payment_per_period can be specified)\n      target_date: \"2030-01-01\"\n      # Expected rate of returns\n      # OPTIONAL\n      payment_per_period: 0\n      # Expected rate of returns\n      # OPTIONAL, REQUIRED if target_date or payment_per_period is set\n      rate: 5\n      # List of accounts where you keep the goal's savings\n      # REQUIRED\n      accounts:\n        - Assets:Equity:**\n## Schedule AL\n# OPTIONAL, DEFAULT: []\nschedule_al:\n  # Code\n  # REQUIRED, ENUM: immovable, metal, art, vehicle, bank, share,\n  # insurance, loan, cash, liability\n  - code: metal\n    accounts:\n      - Assets:Gold\n  - code: bank\n    accounts:\n      - Assets:Checking\n      - Assets:Debt:Cash:FD\n  - code: share\n    accounts:\n      - Assets:Equity:*\n  - code: insurance\n    accounts:\n      - Assets:Debt:Insurance\n\n## Allocation Target\n# OPTIONAL, DEFAULT: []\nallocation_targets:\n  - name: Debt\n    target: 30\n    accounts:\n      - Assets:Debt:*\n      - Assets:Checking\n  - name: Equity\n    target: 60\n    accounts:\n      - Assets:Equity:*\n  - name: Equity Foreign\n    target: 20\n    accounts:\n      - Assets:Equity:NASDAQ\n  - name: Equity Index\n    target: 20\n    accounts:\n      - Assets:Equity:NIFTY\n  - name: Equity Active\n    target: 20\n    accounts:\n      - Assets:Equity:PPFAS\n  - name: Others\n    target: 10\n    accounts:\n      - Assets:Gold\n      - Assets:RealEstate\n\n## Commodities\n# OPTIONAL, DEFAULT: []\ncommodities:\n  - name: NASDAQ\n    # Required, ENUM: mutualfund, stock, nps, unknown\n    type: mutualfund\n    price:\n      # Required, ENUM: in-mfapi, com-yahoo, com-purifiedbytes-nps, co-alphavantage\n      provider: in-mfapi\n      # differs based on provider\n      code: 145552\n    harvest: 1095\n    # Optional, ENUM: equity65, equity35, debt, unlisted_equity\n    tax_category: debt\n  - name: NIFTY\n    type: mutualfund\n    price:\n      provider: in-mfapi\n      code: 120716\n    harvest: 365\n    tax_category: equity65\n  - name: APPLE\n    type: stock\n    price:\n      provider: com-yahoo\n      code: AAPL\n    harvest: 1095\n    tax_category: equity65\n\n## Import Templates\n# OPTIONAL, DEFAULT: []\nimport_templates:\n  - name: SBI Account Statement\n    # Required\n    content: |\n      {{#if (isDate ROW.A \"D MMM YYYY\")}}\n        {{date ROW.A \"D MMM YYYY\"}} {{ROW.C}}\n        {{#if (isBlank ROW.F)}}\n          {{predictAccount prefix=\"Expenses\"}}      {{amount ROW.E}} INR\n          Assets:Checking:SBI\n        {{else}}\n          Assets:Checking:SBI                       {{amount ROW.F}} INR\n          {{predictAccount prefix=\"Income\"}}\n        {{/if}}\n      {{/if}}\n    # Should be a valid handlebar template\n\n## Accounts: account customization\n# OPTIONAL, DEFAULT: []\naccounts:\n  - name: Liabilities:CreditCard:IDFC\n    # Required, name of the account\n    icon: arcticons:idfc-first-bank\n    # Optional, use the UI to select the icon.\n\n## List of user accounts.\n# If the list is empty, then no authentication will be performed\n#\n# OPTIONAL, DEFAULT: []\nuser_accounts:\n  - username: john.doe\n    # Required\n    password: sha256:a96dc73edd639b1c711b006e714bd2ff5bf5c1aecd77d0b3c3370403c66d58e5\n    # Required, password hashed twice with sha256, then prefixed sha256:\n    # echo -n 'secret' | sha256sum | head -c 64 | sha256sum | head -c 64\n
"},{"location":"reference/editor/","title":"Editor","text":"

Paisa uses codemirror that comes with a standard set of keyboard shortcuts. In addition to that, Paisa has few more shortcuts, which are listed below.

"},{"location":"reference/editor/#keyboard-shortcuts","title":"Keyboard shortcuts","text":"Linux Mac Windows Description Ctrl+S Ctrl+S Ctrl+S Save file Ctrl+Shift+I Ctrl+Shift+I Ctrl+Shift+I Prettify Ctrl+F Cmd+F Ctrl+F Open search panel Ctrl+Z Cmd+Z Ctrl+Z Undo Ctrl+Y Cmd+Y Ctrl+Y Redo"},{"location":"reference/import/","title":"Import","text":"

Paisa provides ability to convert CSV, TXT, XLS, XLSX or PDF files to Ledger file format. The import page is made of three components.

Experimental

PDF support is in an experimental stage and may not accurately detect rows.

1) File Preview - You can drag and drop files here to preview the contents.

2) Ledger Preview - This is where the converted ledger file will be shown.

3) Template Editor - This is where you can edit the template.

Each row in the CSV file is converted to a transaction in the ledger. This conversion is controlled by the template.

{{#if (and (isDate ROW.A \"DD/MM/YYYY\") (isBlank ROW.G))}}\n {{date ROW.A \"DD/MM/YYYY\"}} {{ROW.C}}\n    {{predictAccount prefix=\"Expenses\"}}        {{ROW.F}} INR\n    Assets:Checking\n{{/if}}\n

Let's break this down. The first line is a conditional statement. It checks if the row has a date in the first column. You can refer any column using their alphabets. The second line constructs the transaction header. The third line constructs the first posting. The fourth line constructs the second posting.

Effectively a single row in the CSV file is converted to a single transaction like this.

2023/03/28 AMAZON HTTP://WWW.AM IN\n    Expenses:Shopping       249.00 INR\n    Assets:Checking\n

The template is written in Handlebars. Paisa provides a few helper functions to make it easier to write the template.

"},{"location":"reference/import/#template-management","title":"Template Management","text":"

Paisa ships with a few built-in templates. You can also create your own. To create a new template, edit the template and click on the Save As button. User defined custom templates are stored in the configuration file.

Tip

The import system is designed to be extensible and might not be intuitive if you are not accustomed to coding. If you are unable to create a template suitable for your file, please open an issue with a sample file, and we will provide assistance, possibly adding it to the built-in templates.

"},{"location":"reference/import/#template-data","title":"Template Data","text":"
  1. ROW - This is the current row being processed. You can refer to any column using their alphabets. For example, ROW.A refers to the first column, ROW.B refers to the second column and so on. The current row index is available as ROW.index.
Example
{\n  \"A\": \"28/03/2023\",\n  \"B\": \"7357680821\",\n  \"C\": \"AMAZON HTTP://WWW.AM IN\",\n  \"D\": \"12\",\n  \"E\": \"0\",\n  \"F\": \"249.00\",\n  \"G\": \"\",\n  \"index\": 6\n}\n
  1. SHEET - This is the entire sheet. It is an array of rows. You can refer a specific cell using the following syntax SHEET.5.A.
Example
[\n    {\n        \"A\": \"Accountno:\",\n        \"B\": \"49493xxx003030\",\n        \"index\": 0\n    },\n    {\n        \"A\": \"Customer Name:\",\n        \"B\": \"MR John Doe\",\n        \"index\": 1\n    },\n    {\n        \"A\": \"Address:\",\n        \"B\": \"1234, ABC Street, XYZ City, 123456\",\n        \"index\": 2\n    },\n    {\n        \"A\": \"Transaction Details:\",\n        \"index\": 3\n    },\n    {\n        \"A\": \"Date\",\n        \"B\": \"Sr.No.\",\n        \"C\": \"Transaction Details\",\n        \"D\": \"Reward Point Header\",\n        \"E\": \"Intl.Amount\",\n        \"F\": \"Amount(in Rs)\",\n        \"G\": \"BillingAmountSign\",\n        \"index\": 4\n    },\n    {\n        \"A\": \"49493xxx003030\",\n        \"index\": 5\n    },\n    {\n        \"A\": \"28/03/2023\",\n        \"B\": \"7357680821\",\n        \"C\": \"AMAZON HTTP://WWW.AM IN\",\n        \"D\": \"12\",\n        \"E\": \"0\",\n        \"F\": \"249.00\",\n        \"G\": \"\",\n        \"index\": 6\n    },\n    {\n        \"A\": \"28/03/2023\",\n        \"B\": \"7357821997\",\n        \"C\": \"AMAZON HTTP://WWW.AM IN\",\n        \"D\": \"28\",\n        \"E\": \"0\",\n        \"F\": \"575.00\",\n        \"G\": \"\",\n        \"index\": 7\n    }\n]\n
"},{"location":"reference/import/#template-helpers","title":"Template Helpers","text":""},{"location":"reference/import/#eqa-any-b-any-boolean","title":"eq(a: any, b: any): boolean","text":"

Checks if the two values are equal.

"},{"location":"reference/import/#notvalue-any-boolean","title":"not(value: any): boolean","text":"

Negates the given value.

"},{"location":"reference/import/#andargs-any-boolean","title":"and(...args: any[]): boolean","text":"

Returns true if all the arguments are true.

"},{"location":"reference/import/#orargs-any-boolean","title":"or(...args: any[]): boolean","text":"

Returns true if any of the arguments are true.

"},{"location":"reference/import/#gtea-string-number-b-string-number-boolean","title":"gte(a: string | number, b: string | number): boolean","text":"

Checks if a is greater than or equal to b.

"},{"location":"reference/import/#gta-string-number-b-string-number-boolean","title":"gt(a: string | number, b: string | number): boolean","text":"

Checks if a is greater than b.

"},{"location":"reference/import/#ltea-string-number-b-string-number-boolean","title":"lte(a: string | number, b: string | number): boolean","text":"

Checks if a is less than or equal to b.

"},{"location":"reference/import/#lta-string-number-b-string-number-boolean","title":"lt(a: string | number, b: string | number): boolean","text":"

Checks if a is less than b.

"},{"location":"reference/import/#negatevalue-string-number-number","title":"negate(value: string | number): number","text":"

Negates the given value. For example, negate(\"123.45\") will return -123.45

"},{"location":"reference/import/#amountstr-string-default-string-string","title":"amount(str: string, {default?: string}): string","text":"

Converts the given string to a valid amount. If the string is blank, the default value is used. Examples (0.9534) to -0.9534, \u20b9 1,234.56 to 1234.56

"},{"location":"reference/import/#roundstr-string-precision-number-number","title":"round(str: string, {precision?: number}): number","text":"

Rounds the given value to the given precision. If precision is not set, defaults to 0

"},{"location":"reference/import/#isdatestr-string-format-string-boolean","title":"isDate(str: string, format: string): boolean","text":"

Checks if the given string is a valid date in the given format. Refer Day.js for the full list of supported formats.

"},{"location":"reference/import/#predictaccountterms-string-prefix-string-string","title":"predictAccount(...terms: string[], {prefix?: string}): string","text":"

Helps with prediction of account name to be used in a transaction. Let's say you import your Credit Card bill, you would prefer the system to automatically assign the account name for you. predictAccount acts like a search engine. It will try to find a transaction that is similar to the current transaction. The search requires input (referred as terms) and it will match transactions with similar description and will pick the accounts from the top match.

If terms are not provided, the entire ROW will be used.

The prefix is optional and will be used to filter out matching accounts. If no match is found, Unknown will be returned.

{{predictAccount prefix=\"Income\"}}\n{{predictAccount ROW.C ROW.F prefix=\"Income\"}}\n

Tip

Prediction will only work if you have similar transactions in ledger file. It usually means, first time you have to manually fix the Unknown account and then subsequent imports will work

"},{"location":"reference/import/#isblankstr-string-boolean","title":"isBlank(str: string): boolean","text":"

Checks if the given string is blank.

"},{"location":"reference/import/#datestr-string-format-string-string","title":"date(str: string, format: string): string","text":"

Parses the given string as a date in the given format and returns the date in the format YYYY/MM/DD. Refer Day.js for the full list of supported formats.

"},{"location":"reference/import/#findabovecolumn-string-regexp-string-string","title":"findAbove(column: string, {regexp?: string}): string","text":"

Finds the first cell above the current row in the given column. If regexp is provided, the search will continue till a match is found

{{findAbove B regexp=\"LIMITED\"}}\n
"},{"location":"reference/import/#findbelowcolumn-string-regexp-string-string","title":"findBelow(column: string, {regexp?: string}): string","text":"

Finds the first cell below the current row in the given column. If regexp is provided, the search will continue till a match is found

{{findBelow B regexp=\"LIMITED\"}}\n
"},{"location":"reference/import/#acronymstr-string-string","title":"acronym(str: string): string","text":"

Returns the acronym of the given string that is suitable to be used as a commodity symbol. For example, UTI Nifty Next 50 Index Growth Direct Plan will be converted to UNNI

"},{"location":"reference/import/#replacestr-string-search-string-replace-string-string","title":"replace(str: string, search: string, replace: string): string","text":"

Trims the given string.

"},{"location":"reference/import/#regexpteststr-string-regexp-string-boolean","title":"regexpTest(str: string, regexp: string): boolean","text":"

Tests the given string against the given regular expression.

"},{"location":"reference/import/#regexpmatchstr-string-regexp-string-group-number-string","title":"regexpMatch(str: string, regexp: string, {group?: number}): string","text":"

Extract part of a string. Let's say you have Axis Long Term Equity Growth Direct Plan and you want to extract Axis Long Term Equity, you can use {{regexpMatch ROW.C \"(.*) Growth Direct Plan\" group=1}} assuming the string is in the column C. group is optional and defaults to 0.

"},{"location":"reference/import/#textrangefromcolumn-string-tocolumn-string-separator-number-string","title":"textRange(fromColumn: string, toColumn: string, {separator?: number}): string","text":"

Extracts text from the given range of columns. The separator is optional and defaults to \" \".

{{textRange A C separator=\" \"}}\n
"},{"location":"reference/import/#tolowercasestr-string-string","title":"toLowerCase(str: string): string","text":"

Converts the given string to lower case.

"},{"location":"reference/import/#touppercasestr-string-string","title":"toUpperCase(str: string): string","text":"

Converts the given string to upper case.

"},{"location":"reference/import/#matchstr-string-string-string-string","title":"match(str: string, {[string]: string}): string","text":"

Let's say you are trying to import your Credit Card bill and you want map the transaction to a specific expense account based on the description. You can use the match helper to do that. The helper takes a string and a map of key value pairs. The key is the account to be returned if the string matches the value. The value must be a valid regular expression.

{{match ROW.C Expenses:Shopping=\"Amazon|Flipkart\" Expenses:Groceries=\"BigBasket\"}}\n

In case of no match null will be returned. You can combine this with or helper to return a default account.

{{or (match ROW.C Expenses:Shopping=\"Amazon|Flipkart\" Expenses:Groceries=\"BigBasket\")\n     \"Expenses:Unknown\"}}\n
"},{"location":"reference/journal/","title":"Journal","text":"

All your transactions are stored in plain text files called journal. You can organize your transactions into multiple journal files. The journal_path configuration refers your main journal file. The main journal file can refer other journal files using include directive. The include directive supports wildcards * as well. Transactions are sourced only from the main journal file and other journal files included from the main journal file.

include investments.ledger\ninclude expenses/*.ledger\n
"},{"location":"reference/journal/#editor","title":"Editor","text":"

Paisa comes with a journal editor. It allows you to edit all the files with the same file extension as your main journal and in the same or sub directories as your main journal.

"},{"location":"reference/journal/#backup","title":"Backup","text":"

Paisa tries its best to keep your journal safe. It creates a backup of your journal file every time you save it. The backup file is created with the same name as your journal file with a .backup.{timestamp} extension. You can revert back to old versions of your journal file via the editor. You can also delete the backup files from the editor.

Warning

It is recommended to keep your journal files and paisa.yaml under version control or other backup mechanism. Paisa's backup mechanism is not a replacement for a proper backup. You can ignore paisa.db file from your version control system, the data in db file can be recreated from your journal files.

"},{"location":"reference/journal/#syntax","title":"Syntax","text":"

The journal syntax of the features you use normally along with paisa is documented here. Refer ledger documentation for more details.

"},{"location":"reference/journal/#transaction","title":"Transaction","text":"
2022/01/01 Salary\n    Income:Salary:Acme      -100,000 INR\n    Assets:Checking          100,000 INR\n

A transaction should start with a date followed by description. Following that you can have 2 or more postings. The posting line should have at least 2 leading spaces. The account name and the amount should be separated by at least 2 spaces.

"},{"location":"reference/journal/#commodity","title":"Commodity","text":"
2022/01/07 Investment\n    Assets:Checking         -20,000 INR\n    Assets:Equity:NIFTY   168.690 NIFTY @ 118.56 INR\n

commodity cost can be specified using the @ syntax. Here 118.56 is the per unit cost and 168.690 is the quantity you have bought.

"},{"location":"reference/journal/#comment","title":"Comment","text":"
2023/07/01 Rent\n    ; This is a transaction comment\n    Expenses:Rent             15,000 INR\n    Assets:Checking   ; This is a posting comment\n

Any text after ; is treated as a comment. Comment can be at whole transaction level or individual posting level. Comment is also referred as note in many places, both are same.

"},{"location":"reference/journal/#tags","title":"Tags","text":"
2023/07/01 Rent\n    ; Recurring: Rent\n    Expenses:Rent             15,000 INR\n    Assets:Checking\n

Transactions can be tagged with extra metadata called tags. Tag has two parts: tag name and value. In the above example, Recurring is the name and Rent is the value. Tag should be inside comment.

"},{"location":"reference/journal/#include","title":"Include","text":"
include investments.ledger\ninclude expenses/*.ledger\n

Include directive can be used to include other journal files. It supports wildcards *.

"},{"location":"reference/ledger-cli/","title":"Ledger CLI","text":"

Paisa is compatible with ledger, hledger and beancount. By default paisa will try to use ledger, if you prefer to use hledger or beancount instead, change the ledger_cli value in paisa.yaml

# OPTIONAL, DEFAULT: ledger, ENUM: ledger, hledger, beancount\nledger_cli: hledger\n

Paisa ships with ledger binary. If you use hledger or beancount, make sure that the binaries are installed.

"},{"location":"reference/ledger-cli/#unavailable-features","title":"Unavailable Features","text":"

Some of the features that are available in Paisa are not supported by hledger and beancount

"},{"location":"reference/ledger-cli/#hledger","title":"hledger","text":"
  • Recurring (partial) - hledger supports automated transactions, but it doesn't allow to add only metadata to transaction. So some of the examples in the recurring section will not work with hledger. It's possible to add metadata to transactions manually.
"},{"location":"reference/ledger-cli/#beancount","title":"beancount","text":"
  • Budget - budget is based on periodic transactions that is no supported by beancount.

  • Recurring (partial) - beancount doesn't support automated transactions. It's possible to add metadata to transactions manually. Use lowercase for tag name.

  • Search filter in Transactions and Postings pages doesn't support note property.

"},{"location":"reference/recurring/","title":"Recurring","text":"

Some of the transactions recur on a regular interval and it might be useful to know the next due date for such transactions. Recurring page shows the upcoming or recently missed transactions.

Paisa depends on the posting metadata to identify which transactions are recurring. This metadata can be added in couple of ways. Let's say you pay rent every month and you want to mark it as recurring, a typical journal would like below

2023/07/01 Rent\n    Expenses:Rent             15,000 INR\n    Assets:Checking\n\n2023/08/01 Rent\n    Expenses:Rent             15,000 INR\n    Assets:Checking\n

You can manually tag a posting by adding ; Recurring: Rent.

2023/07/01 Rent\n    ; Recurring: Rent\n    Expenses:Rent             15,000 INR\n    Assets:Checking\n\n2023/08/01 Rent\n    ; Recurring: Rent\n    Expenses:Rent             15,000 INR\n    Assets:Checking\n

The first part of the metadata before the colon is called tag name. It should be Recurring. The second part is the tag value. This value is used to group transactions.

Tagging each and every posting can be tiresome. Ledger has a feature called Automated Transaction which can make this process simpler.

= Expenses:Rent\n    ; Recurring: Rent\n

The first line is the predicate and the line below it will get added to any matching posting. By default, it will match the posting account name. But you can target other attributes like payee, amount etc. You can find more examples below, more info about predicate is available on Ledger docs

= expr payee=~/^PPF$/\n    ; Recurring: PPF\n\n= expr payee=~/Mutual Fund/\n    ; Recurring: Mutual Fund\n\n= expr 'account=~/Expenses:Insurance/ and (payee=~/HDFC/)'\n    ; Recurring: Life Insurance\n\n= expr 'account=~/Expenses:Insurance/ and !(payee=~/HDFC/)'\n    ; Recurring: Bike Insurance\n\n= expr payee=~/Savings Interest/\n    ; Recurring: Savings Interest\n

Tip

Include the automated transactions at the top of the main ledger file. Ledger will apply the rules only to transactions that follow the automated transactions.

"},{"location":"reference/recurring/#period","title":"Period","text":"

Paisa will try to infer the recurring period of the transactions automatically, but this might not be perfect. Recurring period can also be explicitly specified via metadata.

= expr payee=~/Savings Interest/\n    ; Recurring: Savings Interest\n    ; Period: L MAR,JUN,SEP,DEC ?\n

Let's say your bank deposits the interest on the last day of the last month of the quarter, we can specify like the example above. Paisa editor recognizes period syntax and shows the upcoming 3 schedules right next to period metadata.

\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 day of the month 1-31\n\u2502  \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 month 1-12 or JAN-DEC\n\u2502  \u2502  \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 day of the week 0-6 (Sunday to Saturday)\n\u2502  \u2502  \u2502\n1  *  ?\n

The syntax of the period is similar to cron, with the omission of seconds and hours.

Field Allowed values Special characters Day of month 1\u201331 * , - ? L W Month 1-12 or JAN-DEC * , - Day of week 0-6 or SUN-SAT * , - ? L

* also known as wildcard represents all valid values. ? means you want to omit the field, usually you use it on the day of month or day of week. L means last day of the month or week. , can be used to specify multiple entries. - can be used to specify range. W means the closest business day to given day of month

Multiple cron expressions can be specified by joining them using |. Refer the wikipedia for more information. If you are not sure, just type it out and the editor will show you whether it is valid and the next 3 schedules if valid.

"},{"location":"reference/recurring/#examples","title":"Examples","text":"
  • Last day of every month ; Period: L * ?
  • 5th every month ; Period: 5 * ?
  • Every Sunday ; Period: ? * 0
  • 1st of Jan and 7th of Feb ; Period: 1 JAN ? | 7 FEB ?
  • Closest business day to the 15th day of every month. ; Period: 15W * ?

Warning

Recurring page will only display a transaction as recurring if there is more than one transaction with the same tag name. If you have only one transaction, wait untill the next transaction is added to see it on the recurring page.

"},{"location":"reference/sheets/","title":"Sheets","text":""},{"location":"reference/sheets/#introduction","title":"Introduction","text":"

Sheet is a notepad calculator that computes the answer as you type. It has full access to your ledger and can be used to calculate the answers for a wide variety of financial questions.

Experimental

Sheet is an experimental feature. Give it a try and let me know how it goes, specially what is missing and what can be improved. The syntax and semantics of sheet may change in future releases.

"},{"location":"reference/sheets/#calculator","title":"Calculator","text":"

Sheet can act as a normal calculator. The example below shows how to calculate the monthly EMI for a home loan.

# Home Loan\nprice = 40,00,000\ndown_payment = 20% * price\nfinance_amount = price - down_payment\ninterest_rate = 8.6%\nterm = 30\n\nn = term * 12\nr = interest_rate / 12\n# EMI\nmonthly_payment = r / (1 - (1 + r) ^ (-n)) * finance_amount\n
# Home Loan\n40,00,000\n8,00,000\n32,00,000\n0\n30\n\n360\n0\n# EMI\n24832\n
"},{"location":"reference/sheets/#function","title":"Function","text":"

Sheets comes with a set of built-in functions. You can also define your own functions. The example below shows how to define a function

# Years to Double\nyears_to_double(rate) = 72 / rate\n\nyears_to_double(2)\nyears_to_double(4)\nyears_to_double(6)\nyears_to_double(8)\nyears_to_double(10)\nyears_to_double(12)\nyears_to_double(14)\n
# Years to Double\n\n\n36\n18\n12\n9\n7\n6\n5\n
"},{"location":"reference/sheets/#query","title":"Query","text":"

Query is what makes sheets powerful. It allows you to query your ledger postings and do calculations on them. The example below shows how to calculate cost basis of your assets so you can report them to Income Tax department.

# Schedule AL\ndate_query = {date <= [2023-03-31]}\ncost_basis(x) = cost(fifo(x AND date_query))\ncost_basis_negative(x) = cost(fifo(negate(x AND date_query)))\n\n# Immovable\nimmovable = cost_basis({account = Assets:House})\n\n# Movable\nmetal = 0\nart = 0\nvehicle = 0\nbank = cost_basis({account = /^Assets:Checking/})\nshare = cost_basis({account =~ /^Assets:Equity:.*/ OR\n                    account =~ /^Assets:Debt:.*/})\ninsurance = 0\nloan = 0\ncash = 0\n\n# Liability\nliability = cost_basis_negative({account =~ /^Liabilities:Homeloan/})\n\n# Total\ntotal = immovable + metal + art + vehicle + bank + share + insurance + loan + cash - liability\n
# Schedule AL\n\n\n\n\n# Immovable\n25,00,000\n\n# Movable\n0\n0\n0\n1,21,402\n66,98,880\n\n0\n0\n0\n\n# Liability\n6,21,600\n\n# Total\n86,98,682\n
"},{"location":"reference/sheets/#syntax","title":"Syntax","text":""},{"location":"reference/sheets/#number","title":"Number","text":"

Sheet allows comma as a separator. % is a syntax sugar for dividing the number by 100. So 8% is same as 0.08.

100,00\n100.00\n-100\n8%\n
"},{"location":"reference/sheets/#operators","title":"Operators","text":"

Sheet supports the following operators. ^ is the exponentiation operator.

1 + 1\n1 - 1\n1 * 1\n1 / 1\n1 ^ 2\n
"},{"location":"reference/sheets/#variable","title":"Variable","text":"

You can define variables using = operator. Variables have to be defined before they are used.

x = 1\ny = 2\n\nz = x + y\n
"},{"location":"reference/sheets/#function_1","title":"Function","text":"

Sheet comes with a set of built-in functions. You can also define your own functions. Function definition starts with the function name and then a list of arguments. The body of the function is a single expression. To call a function, use the function name followed by arguments.

sum(a, b) = a + b\n\nsum(1, 2)\n
"},{"location":"reference/sheets/#query_1","title":"Query","text":"

Query is a first class citizen in sheet. You can think of a query as a list of postings that match the conditions. The query syntax is same as the search syntax used in postings and transactions pages. It has to be enclosed inside a {}. Query can be treated as any other value, can be passed as an argument, can be assigned to a variable. In fact you can combine two queries using AND and OR operator as well.

query = {account = Expenses:Utilities AND payee =~ /uber/i}\n\nupto_this_fy = {date < [2024-04-01]}\nassets = { account =~ /^Assets:.*/ }\nliabilities = { account =~ /^Liabilities:.*/ }\n\nassets_upto_this_fy = upto_this_fy AND assets\nliabilities_upto_this_fy = upto_this_fy AND liabilities\n
What is posting?

2022/01/01 Salary\n    Income:Salary:Acme        -100,000 INR\n    Assets:Checking            100,000 INR\n
In the above transaction, there are two postings. A transaction consists of several postings that sum to zero. If you want to know the cost of your checking account, you would use cost({account = Assets:Checking})

"},{"location":"reference/sheets/#comment","title":"Comment","text":"

Sheet supports single line comments starting with ; or //.

// set x\nx = 1\n; set y\ny = 2\n\nz = x + y // add x and y\n
"},{"location":"reference/sheets/#functions","title":"Functions","text":"

You can find the full list of built-in functions here. This list is very slim as of now, please start a discussion if you want some functions to be added here.

"},{"location":"reference/sheets/#costq-posting-query-number","title":"cost(q: Posting[] | Query): number","text":"

Returns the sum of the cost of all the postings.

"},{"location":"reference/sheets/#balanceq-posting-query-number","title":"balance(q: Posting[] | Query): number","text":"

Returns the sum of the current market value of all the postings.

"},{"location":"reference/sheets/#fifoq-posting-query-posting","title":"fifo(q: Posting[] | Query): Posting[]","text":"

Returns the list of postings after performing a FIFO adjustment. For example, assume you have 3 postings

2020/01/01 Buy\n    Assets:Bank:Checking   100 USD\n2020/02/01 Buy\n    Assets:Bank:Checking   100 USD\n2020/03/01 Sell\n    Assets:Bank:Checking   -50 USD\n

after FIFO adjustment, you will get the following postings

2020/01/01 Buy\n    Assets:Bank:Checking    50 USD\n2020/02/01 Buy\n    Assets:Bank:Checking   100 USD\n

All your sell postings will be adjusted against the oldest buy postings and you will have the remaining buy postings.

"},{"location":"reference/sheets/#negateq-posting-query-posting","title":"negate(q: Posting[] | Query): Posting[]","text":"

Negates the amount and quantity of all the postings. This would be useful when you want to do some calculation on liabilities or income which are negative in nature.

"},{"location":"reference/user-authentication/","title":"User Authentication","text":"

You can setup username and password to make sure only you can access the application. Go to Configuration page and expand the User Accounts section. You can click the icon to add a new username and password. Once you save the configuration, you will get logged out if you had not logged in earlier via another account.

It is important to understand that authentication only protects the application user interface. If someone can access your computer and they can access the folder where Paisa stores the ledger and database files, they will be able to view your data.

"},{"location":"reference/user-authentication/#implementation-details","title":"Implementation details","text":"

Paisa uses cryptographic hash function sha-256 to convert your password to digest before storing it in the configuration file. This has few implications. No one can look at the configuration file and get the password, this includes you as well. If you forget the password, you can remove the user accounts from configuration file to get back access.

Warning

If you run paisa on a server and access it over public internet, make sure to use it over https and use a strong password. If you run it over plain http, man in the middle attack can be performed to obtain the data including your password.

"},{"location":"reference/goals/","title":"Goals","text":"

Goal helps you track your financial objective and progress. You can create a goal for any financial objective you have, such as saving for a vacation, or building an emergency fund or planning for retirement.

Paisa currently supports two types of goals:

  1. Retirement
  2. Savings

More goal types will be added in the future. Feel free to create a discussion if you have any suggestions.

"},{"location":"reference/goals/#create-goal","title":"Create Goal","text":"

To add a new goal, go to the Configuration page and expand the goals section. You would see a list of goal types. Expand the type you want to add and click on the icon to add a new goal. The configuration details are available in the respective goal type pages.

Under Development

Goals is currently under development and you might see changes with every new release. If you want to share feedback, this is a good time to do so.

"},{"location":"reference/goals/retirement/","title":"Retirement","text":"

Paisa will help you plan your retirement and track your progress. The first part is figuring out what should be your retirement corpus. This will be your target. Instead of specifying the amount explicitly, you can specify your expected yearly expenses and the safe withdrawal rate.

goals:\n  retirement:\n    - name: Retirement\n      icon: mdi:palm-tree\n      swr: 3.3\n      yearly_expenses: 1100000\n

If you use paisa to track expenses, instead of specifying the yearly_expenses, you can specify the list of accounts. Paisa will take the average of the last 3 year expenses

goals:\n  retirement:\n    - name: Retirement\n      icon: mdi:palm-tree\n      swr: 2\n      expenses:\n        - Expenses:Entertainment\n        - Expenses:Gift\n        - Expenses:Insurance\n        - Expenses:Misc\n        - Expenses:Shopping\n        - Expenses:Utilities\n

Now that the target is specified, you need to specify the list of accounts where you keep your retirement savings.

goals:\n  retirement:\n    - name: Retirement\n      icon: mdi:palm-tree\n      swr: 2\n      expenses:\n        - Expenses:Entertainment\n        - Expenses:Gift\n        - Expenses:Insurance\n        - Expenses:Misc\n        - Expenses:Shopping\n        - Expenses:Utilities\n      savings:\n        - Assets:Equity:*\n        - Assets:Debt:*\n
"},{"location":"reference/goals/savings/","title":"Savings","text":"

Savings represents a general financial objective that you want to achieve, like buying a car, or a house, or a vacation.

goals:\n  savings:\n    - name: House\n      target: 5000000\n      icon: fluent-emoji-high-contrast:house-with-garden\n      accounts:\n        - Assets:Equity:*\n        - Assets:Debt:*\n

Specify the target amount, and the accounts that you keep the money in.

"},{"location":"reference/goals/savings/#forecast","title":"Forecast","text":"

When you save towards an objective, you will have a target date in mind. In the below config, you are specifying the target date and rate. Paisa will calculate the monthly contribution required to achieve the goal.

goals:\n  savings:\n    - name: House\n      target: 5000000\n      target_date: 2030-05-01\n      rate: 10\n      icon: fluent-emoji-high-contrast:house-with-garden\n      accounts:\n        - Assets:Equity:*\n        - Assets:Debt:*\n

If on the other hand, you know how much you can afford to save every month, but want to know when the goal will be achieved, you can specify the payment per period and the rate. Paisa will calculate the target date.

goals:\n  savings:\n    - name: House\n      target: 5000000\n      payment_per_period: 50000\n      rate: 10\n      icon: fluent-emoji-high-contrast:house-with-garden\n      accounts:\n        - Assets:Equity:*\n        - Assets:Debt:*\n
"},{"location":"reference/goals/savings/#math","title":"Math","text":"

This section will give some rough idea of how the calculations are done. You can skip this section if you are not interested in the math.

F V + P V \u00d7 ( 1 + R A T E ) N P E R + P M T \u00d7 ( 1 + R A T E ) N P E R \u2212 1 R A T E = 0 FV + PV \\times (1+RATE)^{NPER} + PMT \\times \\frac{(1+RATE)^{NPER} - 1}{RATE} =0

Where

Variable Description Paisa FV Future Value target PV Present Value Current Savings PMT Payment per period payment_per_period / Monthly Investment needed RATE Rate of return rate NPER Number of periods target_date

Out of the 5 variables, if you know any 4, the 5th can be calculated by solving the equation. You can refer the blog post for more details.

"},{"location":"reference/tax/","title":"Tax","text":"

Paisa provides few features to help with tax filing and tax optimization.

"},{"location":"reference/tax/#disclaimer","title":"Disclaimer","text":"

The author of this tool is not an accountant, the calculations are made based on their interpretation of rules and regulation. This tool is distributed free hoping it would be useful. The users are advised to consult a tax accountant before making any decision based on the information provided here. Check the LICENSE of paisa for more details.

"},{"location":"reference/tax/capital-gains/","title":"Capital Gains","text":"

Mutual Funds are considered as capital asset and capital gains tax will be charged on any gains. Capital Gains page shows the financial year wise capital gains tax based on the withdrawal transaction. The sum total, account wise breakdown, and per buy/sell match information are available.

Only commodities with tax_category are considered. Please check Tax Harvesting page for configuration details.

"},{"location":"reference/tax/capital-gains/#gain","title":"Gain","text":"

The difference between the purchase and sell price.

"},{"location":"reference/tax/capital-gains/#taxable-gain","title":"Taxable Gain","text":"

The gain after applying Indexation or Grandfathering provision.

Based on the duration between the purchase and sell date, an asset might be classified as Short Term or Long Term.

"},{"location":"reference/tax/capital-gains/#short-term-tax","title":"Short Term Tax","text":"

This would be a percentage of the Taxable Gain. The percentage varies based on the asset class.

"},{"location":"reference/tax/capital-gains/#long-term-tax","title":"Long Term Tax","text":"

This would be a percentage of the Taxable Gain. The percentage varies based on the asset class.

"},{"location":"reference/tax/capital-gains/#taxable-at-slab-rate","title":"Taxable at Slab Rate","text":"

There are cases where the gain would be added to taxable income and charged Slab rate. Since the tax rate would depend on the person, the whole taxable amount is shown instead of the tax. You can multiply this with your slab rate to get the tax amount.

"},{"location":"reference/tax/schedule-al/","title":"Schedule AL","text":"

As per the Indian Income tax law, citizens are obligated to report their entire Assets and Liabilities if the total income exceeds \u20b950 lakh. Paisa helps with the computation of the amount.

code Section Details immovable A (1) Immovable Assets metal B (1) (i) Jewellery, bullion etc. art B (1) (ii) Archaeological collections, drawings, painting, sculpture or any work of art vehicle B (1) (iii) Vehicles, yachts, boats and aircrafts bank B (1) (iv) (a) Financial assets: Bank (including all deposits) share B (1) (iv) (b) Financial assets: Shares and securities insurance B (1) (iv) (c) Financial assets: Insurance policies loan B (1) (iv) (d) Financial assets: Loans and advances given cash B (1) (iv) (e) Financial assets: Cash in hand liability C (1) Liabilities

All you need to do is to specify the accounts that belong to each section. Paisa will compute the total as on the last day of the previous financial year.

schedule_al:\n    - code: bank\n      accounts:\n          - Assets:Checking\n    - code: share\n      accounts:\n          - Assets:Equity:*\n          - Assets:Debt:*\n
"},{"location":"reference/tax/tax-harvesting/","title":"Tax Harvesting","text":"

Gains from asset types like Mutual Fund, Stock are subject to capital gains tax. The taxation rate itself differs based on how long you hold your investment, whether it's debt or equity, whether you have more than 1 Lakh gains in a year etc. To further complicate things, there might be exit load applicable.

Paisa takes a generic approach and let the user configure when a commodity is safe to harvest. There are two fields related to tax harvesting.

  1. harvest - specifies the number of days after which the commodity is eligible for tax harvesting. This should be set based on fund exit load, fund category etc

  2. tax_category - This defines how the taxes are calculated as the government usually tweaks the tax code regularly with various rules like grandfathering, cost inflation index adjustment, etc.

    1. equity65 - This is for 65% or more investment in Indian equity.

    2. equity35 - This if for 35% or more investment in India equity but less than 65%

    3. debt - This is for debt funds.

    4. unlisted_equity - This is for unlisted foreign on Indian equity.

commodities:\n  - name: NIFTY\n    type: mutualfund\n    code: 120716\n    harvest: 365\n    tax_category: equity65\n  - name: ABSTF\n    type: mutualfund\n    code: 119533\n    harvest: 1095\n    tax_category: debt\n

The tax harvest page will show the list of accounts eligible for harvesting.

"},{"location":"reference/tax/tax-harvesting/#multiple-folios","title":"Multiple Folios","text":"

Paisa uses FIFO method within an Account. If you have multiple folios, this might result in incorrect values. The issue can be solved by using a different Account for each folio.

"},{"location":"blog/archive/2024/","title":"2024","text":""},{"location":"blog/category/configuration/","title":"configuration","text":""},{"location":"blog/category/locale/","title":"locale","text":""}]} \ No newline at end of file +{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"]},"docs":[{"location":"","title":"Home","text":"INR USD EURO
2022/01/01 Salary\n    Income:Salary:Acme     -100,000 INR\n    Assets:Checking         100,000 INR\n\n2022/01/03 Rent\n    Assets:Checking         -20,000 INR\n    Expenses:Rent\n\n2022/01/07 Investment\n    Assets:Checking         -20,000 INR\n    Assets:Equity:NIFTY   168.690 NIFTY @ 118.56 INR\n
2022/01/01 Salary\n    Income:Salary:Acme      $-5,000\n    Assets:Checking          $5,000\n\n2022/01/03 Rent\n    Assets:Checking         $-2,000\n    Expenses:Rent\n\n2022/01/07 Investment\n    Assets:Checking         $-1,000\n    Assets:Equity:AAPL   6.452 AAPL @ $154.97\n
commodity \u20ac\n    format \u20ac1.000,00\n\ncommodity AAPL\n    format 1.000,00 AAPL\n\n2022/01/01 Salary\n    Income:Salary:Acme      \u20ac-5.000\n    Assets:Checking          \u20ac5.000\n\n2022/01/03 Rent\n    Assets:Checking         \u20ac-2.000\n    Expenses:Rent\n\n2022/01/07 Investment\n    Assets:Checking      \u20ac-1.000,02\n    Assets:Equity:AAPL   6,453 AAPL @ \u20ac154,97\n

Install Demo

  • Builds on top of the ledger double entry accounting tool.
  • Your financial data never leaves your system.
  • The journal and configuration information are stored in plain text files that can be easily version controlled. You can collaborate with others by giving access to the files.
  • Track the latest market price of your Mutual Fund, NPS Fund and Stock holdings.
  • Track and budget your Expenses.
  • Convert CSV, Excel and PDF files to Ledger journal.
  • Track your goals.
  • View your recurring transactions.
  • Plan your retirement.
  • And many more visualizations to help you make any financial decisions.
"},{"location":"#personal-finance-manager","title":"Personal Finance Manager","text":""},{"location":"faq/","title":"FAQs","text":"

I already use ledger/hledger/beancount. How do I get started?

Go through the installation docs and get the app working. Go to configuration page and update journal_path, ledger_cli, default_currency and locale. At this point you should be able to view your journal data. Read the accounts docs to understand the account naming conventions followed by paisa.

How do I get started?

You have installed paisa and gone through the demo and you like it, but you don't know what to do next. There is no way you would sit and type all the transactions you have made in the last decade or so.

Paisa is an accounting application and you can focus on things that matters to you the most. For example, if you are not interested in tracking expenses, you can just have a single expense transaction per month. You decide the granularity at which you want to record the transactions. Just recording a few transactions per month like your salary, monthly expense and investments will go a long way and will give you pretty good picture of your finances.

Mac Desktop app fails with executable file not found in $PATH error

Mac Desktop apps are usually started with different PATH than what you would normally get in a Terminal app. Paisa does a fallback search in the following folders before throwing the error. Check if your executable binary is in any of the folder listed below, if not, create a symbolic link from one of the folders to your executable binary.

/bin\n/usr/bin\n/usr/local/bin\n/sbin\n/usr/sbin\n/opt/homebrew/bin\n
"},{"location":"manifesto/","title":"Manifesto","text":""},{"location":"manifesto/#1-data-ownership","title":"1. Data Ownership","text":"

User owns the data. It should be possible to migrate all the data to another app or service. Paisa will strive to make this as easy as possible by choosing open standards and formats.

Ledger text format is used to store all the transaction data.

"},{"location":"manifesto/#2-privacy","title":"2. Privacy","text":"

User's data is private. Paisa will not collect or send any data to any server1. Paisa will not use any third party analytics or tracking on the app2.

Paisa's source code is open source and could be audited by anyone.

"},{"location":"manifesto/#3-longevity","title":"3. Longevity","text":"

The app should be available for a long time. It takes a lot of effort to collect and maintain the transaction data. The app should not just disappear one day. Paisa will strive to avoid unnecessary dependencies and build a self contained app.

Paisa is licensed under AGPL v3, which helps with this issue to some extent. I have yet to figure out a solution to make the app development and maintenance process sustainable in the long term. But rest assured, any decision that would be made related to this will not override the first two points.

  1. Paisa fetches commodity price information from third party servers. Since Paisa will send the commodity identifier to the server, the third party server might be able to connect the commodity list with the user's IP address. This is an opt-in feature, as you have to explicitly configure Paisa to fetch price. VPN could be used if you want to avoid this.\u00a0\u21a9

  2. This doesn't include the website paisa.fyi, which is hosted on third party servers and has consent based analytics.\u00a0\u21a9

"},{"location":"blog/","title":"Blog","text":""},{"location":"blog/2024/01/03/localization/","title":"Localization","text":"

The way numbers are formatted varies across various countries. In this post, I am going to talk about how to configure localization in Paisa so you can use the number formatting you are familiar with.

The User Interface localization is controlled by configuration, and the Journal file localization is controlled by the commodity directive.

"},{"location":"blog/2024/01/03/localization/#user-interface","title":"User Interface","text":""},{"location":"blog/2024/01/03/localization/#locale","title":"locale","text":"

The way the numbers are formatted by the User Interface is controlled by the configuration key called locale. By default, this value is set to en-IN. It can be edited via the configuration page. The value is made of two parts: the first part is the language name, and the second part is the region name. Refer to Wikipedia for the full list of supported language and country codes.

"},{"location":"blog/2024/01/03/localization/#default_currency","title":"default_currency","text":"

Paisa supports multiple currencies, but it needs you to set one of the currencies as the default currency. The User Interface shows all the numbers in the default currency.

"},{"location":"blog/2024/01/03/localization/#display_precision","title":"display_precision","text":"

Paisa also allows you to control the number of digits shown after the decimal point. By default, it's set to zero.

"},{"location":"blog/2024/01/03/localization/#journal","title":"Journal","text":"

In most cases, you don't have to worry about the journal file since you can enter the value in the correct format and the ledger will parse it fine. But if you want to follow European number formatting, then you would have to use commodity directive to declare the number formatting. In the example below, we instruct the ledger to treat , as decimal separator and . as thousand separator.

commodity EUR\n    format 1.000,00 EUR\n\n2024/01/01 Salary\n    Income:Salary:Acme                    -11.000,00 EUR\n    Assets:Checking                        11.000,00 EUR\n
"},{"location":"getting-started/installation/","title":"Installation","text":"

Paisa is available in two formats: a Desktop Application and a CLI (Command Line Interface). Both provide the same list of features, with the primary difference being how the user interface is launched.

"},{"location":"getting-started/installation/#desktop-application","title":"Desktop Application","text":"LinuxMacWindows
  • Download the prebuilt binary named paisa-app-linux-amd64.deb
  • You can install it either by double clicking the deb file or run the following commands in a Terminal
# cd ~/Downloads\n# sudo dpkg -i paisa-app-linux-amd64.deb\n
  • Download the prebuilt binary named paisa-app-macos-amd64.dmg
  • Open the dmg file and drag the Paisa app into Application folder
  • Since the app is not signed1, Mac will show a warning when you try to open the app. You can check the support page for more details. If you don't get any option to open the app, go to the Application folder, right click on the icon and select open. Usually, this should present you with an option to open.
  • Paisa will store all your journals, configuration files, and other related files in a folder named paisa which will be located in your Documents folder. When you open the app on your Mac for the first time, a permission dialog will appear. Click Allow, then close and reopen the app.
  • Download the prebuilt binary named paisa-app-windows-amd64.exe
  • Since the app is not signed1, Windows will show multiple warnings, You might have to click Keep anyway, More info, Run anyway etc.
  • Paisa will store all your journals, configuration files, and other related files in a folder named paisa which will be located in your Documents folder.
"},{"location":"getting-started/installation/#third-party-hosted-options-2","title":"Third Party Hosted Options 2","text":"PikaPods

PikaPods lets you run Paisa on a server with a few clicks. It handles app upgrades, backup and hosting for you. Make sure to setup a user account post installation.

"},{"location":"getting-started/installation/#cli","title":"CLI","text":"LinuxMacWindows
  • Download the prebuilt binary named paisa-cli-linux-amd64
  • Run the following commands in a Terminal
# cd ~/Downloads\n# mv paisa-cli-linux-amd64 paisa\n# chmod u+x paisa\n# mv paisa /usr/local/bin\n
  • Download the prebuilt binary named paisa-cli-macos-amd64
  • Run the following commands in a Terminal
# cd ~/Downloads\n# mv paisa-cli-macos-amd64 paisa\n# chmod u+x paisa\n# xattr -dr com.apple.quarantine paisa\n# mv paisa /usr/local/bin\n
  • Download the prebuilt binary named paisa-cli-windows-amd64.exe
  • Since the binary is not signed1 with a certificate, you might get a warning from Windows. You would have to click keep anyway.
  • Run the following command in a Windows PowerShell. Make sure you are in the correct folder. You should see something like PS C:\\Users\\yourname>
PS C:\\Users\\john> mv .\\Downloads\\paisa-cli-windows-amd64.exe .\\paisa.exe\n
  • The paisa.exe binary will be placed in the user's home directory. You can access it via PowerShell. Just open a new PowerShell window, which will start in the home directory. Then, you can run .\\paisa.exe serve

Tip

Paisa depends on the ledger binary. The prebuilt paisa binaries come with an embedded ledger binary and will use it if it's not already installed on your system. If you prefer to install the ledger yourself, follow the installation instructions on ledger site.

"},{"location":"getting-started/installation/#cli-quick-start","title":"CLI Quick Start","text":"

Paisa will store all your journals, configuration files, and other related files in a folder named paisa which will be located in your Documents folder.

LinuxMacWindows
# paisa serve\n
# paisa serve\n
PS C:\\Users\\john> .\\paisa.exe serve\n

Go to http://localhost:7500. Read the tutorial to learn more.

"},{"location":"getting-started/installation/#docker","title":"Docker","text":"

Paisa CLI is available on dockerhub.

LinuxMac
# mkdir -p /home/john/Documents/paisa/\n# docker run -p 7500:7500 -v /home/john/Documents/paisa/:/root/Documents/paisa/ ananthakumaran/paisa:latest\n
# mkdir -p /Users/john/Documents/paisa/\n# docker run -p 7500:7500 -v /Users/john/Documents/paisa/:/root/Documents/paisa/ ananthakumaran/paisa:latest\n
"},{"location":"getting-started/installation/#nix-flake","title":"Nix Flake","text":"

Paisa CLI is available as a nix flake.

LinuxMac
# nix profile install github:ananthakumaran/paisa\n
# nix profile install github:ananthakumaran/paisa\n
  1. I offer Paisa as a free app, and I don't generate any revenue from it. Code signing would require me to pay $99 for Mac and approximately $300 for Windows each and every year to get the necessary certificates. I can't justify spending that much for an app that doesn't generate any income. Unfortunately, as a result, you would have to jump through hoops to get it working.\u00a0\u21a9\u21a9\u21a9

  2. As the name implies, these are third party hosting solutions operated by independent companies. I may receive affiliate compensation for linking to their websites.\u00a0\u21a9

"},{"location":"getting-started/tutorial/","title":"Tutorial","text":"

This tutorial will introduce all the concepts necessary to get started. Paisa builds on top of the ledger1, a command line tool that follows the principles of plain text accounting. ledger primarily focuses on command line users and doesn't provide any graphical user interface. Paisa aims to create a low-friction graphical user interface on top of ledger, thereby making it accessible to a wider range of users.

As an end user, you should be familiar with the terms and concepts used by ledger, which we will cover below. Paisa comes with an embedded ledger and you are not required to use ledger via command line unless you want to.

Tip

Even though the tutorial focuses on Indian users, Paisa is capable of handling any currency. You can change the default currency, locale and financial year starting month etc. Check the configuration reference for more details.

"},{"location":"getting-started/tutorial/#journal","title":"Journal","text":"

A journal file captures all your financial transactions. A transaction may represent a mutual fund purchase, retirement contribution, grocery purchase and so on. Paisa creates a journal named main.ledger, Let's add our first transaction there. To open the editor, go to Ledger Editor

2022/01/01/*(1)!*/ Salary/*(2)!*/\n    Income:Salary:Acme/*(3)!*/   -100,000 INR/*(6)!*/\n    Assets:Checking/*(4)!*/    /*(5)!*/100,000 INR\n
  1. Transaction Date
  2. Transaction description, also called as Payee
  3. Debit Account
  4. Credit Account
  5. Amount
  6. Currency

ledger follows the double-entry accounting system. In simple terms, it tracks the movement of money from debit account to credit account. Here Income:Salary:Acme is the debit account and Assets:Checking is the credit account. The date at which the transaction took place and a description of the transaction is written in the first line followed by the list of credit or debit entry. Account naming conventions are explained later. The : in the account name represents hierarchy.

2022/01/01 Salary\n    Income:Salary:Acme      -100,000 INR\n    Assets:Checking          100,000 INR\n\n2022/02/01 Salary\n    Income:Salary:Acme      -100,000 INR\n    Assets:Checking          100,000 INR\n\n2022/03/01 Salary\n    Income:Salary:Acme      -100,000 INR\n    Assets:Checking          100,000 INR\n

Let's add few more transactions. As you edit your journal file, the balance of the journal will be shown on the right hand side.

         300,000 INR  Assets:Checking\n        -300,000 INR  Income:Salary:Acme\n--------------------\n                   0\n

You would notice zero balance and a checking account with 3 lakhs and an income account with -3 lakhs. Double-entry accounting will always results in 0 balance since you have to always enter both the credit and debit side.

Let's say your company deducts 12,000 INR and contributes it to EPF, we could represent it as follows

2022/01/01 Salary\n    Income:Salary:Acme    -100,000 INR\n    Assets:Checking         88,000 INR\n    Assets:Debt:EPF         12,000 INR\n\n2022/02/01 Salary\n    Income:Salary:Acme    -100,000 INR\n    Assets:Checking         88,000 INR\n    Assets:Debt:EPF         12,000 INR\n\n2022/03/01 Salary\n    Income:Salary:Acme    -100,000 INR\n    Assets:Checking         88,000 INR\n    Assets:Debt:EPF         12,000 INR\n

You can now see the use of : hierarchy in the account name.

         300,000 INR  Assets\n         264,000 INR    Checking\n          36,000 INR    Debt:EPF\n        -300,000 INR  Income:Salary:Acme\n--------------------\n                   0\n
"},{"location":"getting-started/tutorial/#commodity","title":"Commodity","text":"

So far we have only dealt with INR. ledger can handle commodity as well. Let's say you are also investing 10,000 INR in UTI Nifty Index Fund and 10,000 INR in ICICI Nifty Next 50 Index Fund every month.

2018/01/01 Investment\n    Assets:Checking               -20,000 INR\n    Assets:Equity:NIFTY        148.0865 NIFTY @ 67.5281 INR\n    Assets:Equity:NIFTY_JR  358.6659 NIFTY_JR @ 27.8811 INR\n\n2018/02/01 Investment\n    Assets:Checking               -20,000 INR\n    Assets:Equity:NIFTY        140.2870 NIFTY @ 71.2824 INR\n    Assets:Equity:NIFTY_JR  363.2242 NIFTY_JR @ 27.5312 INR\n\n2018/03/01 Withdrawal\n    Assets:Checking                          6775.49 INR\n    Income:CapitalGains:Equity:NIFTY          -22.68 INR\n    Assets:Equity:NIFTY          -100 NIFTY {67.5281 INR} [2018/01/01] @ 67.7549 INR\n

Let's consider 148.0865 NIFTY @ 67.5281 INR. Here NIFTY is the name of the commodity and we have bought 148.0865 units at 67.5281 INR per unit.

The withdrawal transaction is bit more involved. When you buy a commodity, you buy them at a specific price on a specific date called lot. When you sell, you usually need to record which lot you are selling for taxation purpose, usually FIFO. -100 NIFTY {67.5281 INR} [2018/01/01] @ 67.7549 INR means you are selling NIFTY at price 67.7549 INR that was bought on 2018/01/01 at 67.5281 INR. The gain or loss amount comes from the capital gains account Income:CapitalGains:Equity:NIFTY

Paisa has support for fetching commodity price history from few providers. Go to Configuration page and expand the Commodities section. You can click the icon to add a new one. Edit the name to NIFTY. Click the icon near Price section and select the price provider details. Once done, save the configuration and click the Update Prices from the top right hand side menu. If you had done everything correctly, you would see the latest price of the commodity under Assets Balance

"},{"location":"getting-started/tutorial/#interest","title":"Interest","text":"

There are many instruments like EPF, FD, etc that pay interest at regular intervals. We can treat it as just another transaction. Any income account that has a prefix Income:Interest: can be used as the debit account. It's not mandatory to specify the amount at bot side. If you leave one side, ledger will deduct it.

2022/03/31 EPF Interest\n    Income:Interest:EPF     -5,000 INR\n    Assets:Debt:EPF\n
           5,000 INR  Assets:Debt:EPF\n          -5,000 INR  Income:Interest:EPF\n--------------------\n                   0\n
"},{"location":"getting-started/tutorial/#configuration","title":"Configuration","text":"

All the configuration related to paisa is stored in a yaml file named paisa.yaml. The configuration can be edited via the web interface. The sequence in which it looks for the file is described below

  1. PAISA_CONFIG environment variable
  2. via --config flag
  3. Current working directory
  4. paisa/paisa.yaml file inside User Documents folder.

If it can't find the configuration file, it will create a default configuration file named paisa/paisa.yaml inside User Documents folder. The default configuration is tuned for Indians, users from other countries would have to change the default_currency and locale. Check the configuration reference for details.

"},{"location":"getting-started/tutorial/#update","title":"Update","text":"

Paisa fetches the latest price of the commodities only when update command is used. Make sure to run paisa update command after you make any changes to your journal file or you want to fetch the latest value of the commodities. The update can be performed from the UI as well via the dropdown in the top right hand side corner.

  1. hledger and beancount are also supported, refer Ledger CLI for more information.\u00a0\u21a9

"},{"location":"reference/accounts/","title":"Accounts","text":"

If you take a typical transaction, money moves between two parties. In ledger, you call them Account. At least two accounts are involved in any transaction. Accounts are also hierarchical. This helps with the organization. For example you can treat EPF and PPF as two accounts namely Assets:Debt:EPF and Assets:Debt:PPF. The hierarchy helps you ask questions like what is the balance of Assets:Debt, which will include both EPF and PPF.

Even though ledger doesn't have any strict Account naming convention, Paisa expects you to follow the standard naming convention.

There are five types of account namely

  1. Assets
  2. Liabilities
  3. Income
  4. Expenses
  5. Equity

All the accounts you create should be under one of these accounts. This naming convention is a necessity, because without which, it's not possible to tell whether you are spending money or investing money. A transaction from Assets account to Expenses account implies that you are spending money.

Money typically flows from Income to Assets, from Assets to either Expenses, Liabilities or other Assets, from Liabilities to Expenses.

graph LR\n  I[Income] --> A[Assets];\n  A --> E[Expenses];\n  A --> A;\n  A --> L[Liabilities];\n  L --> E[Expenses];

As a general principle, try not to create too many accounts at second level. The UI works best when you create less than or equal to 12 second level accounts under each type. For example, you can have 12 accounts under Expenses. But if you want more, try to add them under 3rd level, example Expenses:Food:Subway.

"},{"location":"reference/accounts/#assets","title":"Assets","text":"

All your assets should go under Assets:. The level of granularity is up to you. The recommended convention is to use Assets:{instrument_type}:{instrument_name}. The instrument type may be Cash, Equity, Debt, etc. The instrument name may be the name of the fund, stock, etc

"},{"location":"reference/accounts/#checking","title":"Checking","text":"

Assets:Checking is a special account where you keep your money for daily use. This will be included in your net worth, but will not be treated as an investment. So gain page for example, will exclude this account and won't show the returns. If you have multiple checking accounts, you can use sub accounts as well, for example Assets:Checking:HDFC and Assets:Checking:AXIS.

The distinction is necessary because Checking account is an asset, but not an investment. So you ideally you want to disregard them when you calculate your absolute returns etc.

"},{"location":"reference/accounts/#income","title":"Income","text":"

All your income should come from Income:. The typical way is to treat each employer as a separate account like Income:Salary:{company}

"},{"location":"reference/accounts/#interest","title":"Interest","text":"

Income:Interest is a special type of account from the perspective of returns calculation. Let's assume you have bought APPLE stock. You might be buying them at regular intervals. To calculate your returns, we can compute the difference between purchase price and current price.

Now in case of FD, you will get your interest credited to your account. The returns is the difference between the amount you deposited and the final balance. It's essential we need to know which transactions are deposits and which are interest credits.

Any money that comes from the sub account of Income:Interest will be treated as interest. This convention allows paisa to calculate the returns of any debt instrument without explicitly specifying anything else.

  • Income:Interest:{name} - interest debit account
"},{"location":"reference/accounts/#capital-gains","title":"Capital Gains","text":"
2018/03/01 Withdrawal\n    Assets:Checking                  6775.49 INR\n    Income:CapitalGains:Equity:NIFTY  -22.68 INR\n    Assets:Equity:NIFTY               -100 NIFTY {67.5281 INR} [2018/01/01] @ 67.7549 INR\n

Let's say you have an asset account named Assets:{name} and you make some profit when you sell the asset, this profit should come from capital gains account named Income:CapitalGains:{name}.

"},{"location":"reference/accounts/#expenses","title":"Expenses","text":"

All your expenses should go to Expenses:{category} accounts. You can also have more than 2 levels as well. The expense page will roll it up to 2 level wherever necessary.

"},{"location":"reference/accounts/#tax","title":"Tax","text":"

Income tax paid to government should be credited to Expenses:Tax account. This is used to calculate your Net Income and your Savings Rate. If you want to track different types of taxes, you can use sub accounts as well, for example Expenses:Tax:Income and Expenses:Tax:GST.

"},{"location":"reference/accounts/#equity","title":"Equity","text":"

Equity is used in rare cases where you want to balance the transaction, but none of the other accounts are suitable for the purpose. Let's say you have 1000 INR in your real bank account and you want your checking account in Paisa to have same balance, you can use Equity account to balance the transaction.

2022/01/01 Opening Balance\n    Assets:Checking:SBI       1000 INR\n    Equity:OpeningBalance\n
"},{"location":"reference/accounts/#icons","title":"Icons","text":"

Each account is associated with an icon and is shown along with the account name in most places. Paisa assigns icon based on few simple rules and it usually falls back to a generic icon. To modify the icon, go to the configuration page, add a new Account and specify the name of your account and then select icon of your choice. Paisa ships with four icon sets.

  • Arcticons
  • Font Awesome Regular, Solid and Brands
  • Material Design Icons
  • Fluent Emoji High Contrast

Experimental

There is a wide range of free icons available, but adding each icon set to Paisa would increase the app binary size. So a balance has to be struck between the number of icons and the app size. Feel free to start a discussion if you feel strongly about any icon set. The current icon sets are not final, they may be replaced if a better alternative is found.

"},{"location":"reference/allocation-targets/","title":"Allocation Targets","text":"

Paisa allows you to set a allocation target for a group of accounts which might represent your assets like mutual funds, stocks etc. The allocation page shows how far your current allocation is from the allocation target. For example, to keep a 40:60 split between debt and equity, use the following configuration. The account name can have * which matches any characters

allocation_targets:\n  - name: Debt\n    target: 40\n    accounts:\n      - Assets:Debt:*\n  - name: Equity\n    target: 60\n    accounts:\n      - Assets:Equity:*\n
"},{"location":"reference/analysis/","title":"Analysis","text":"

Ledger represents everything except currency as commodities. A commodity could represent physical object like Gold or certificates like Stock, Bond etc. Some commodities like Mutual Fund is a container for Securities. When you own a mutual fund unit, you indirectly own these securities.

The Analysis page unwraps the container and shows you what securities you own along with their amount and percentage. It also categorizes the securities by their industry and rating.

Experimental

The data that powers this page comes from various sources and might not be 100% accurate. Before you make any decision based on this information, double check via different source.

"},{"location":"reference/budget/","title":"Budget","text":"

Paisa supports a simple budgeting system. Let's say you get 50000 INR at the beginning of the month. You want to budget this amount and figure out how much you can spend on each category.

Let's add a salary transaction to the ledger:

2023/08/01 Salary\n    Income:Salary:Acme         -50,000 INR\n    Assets:Checking\n

Now you have 50k in your checking account. Let's budget this amount:

~ Monthly in 2023/08/01\n    Expenses:Rent               15,000 INR\n    Expenses:Food               10,000 INR\n    Expenses:Clothing            5,000 INR\n    Expenses:Entertainment       5,000 INR\n    Expenses:Transport           5,000 INR\n    Expenses:Personal            5,000 INR\n    Assets:Checking\n

The ~ character indicates that this is a periodic transaction. This is not a real transaction, but used only for forecasting purposes. You can read more about periodic expressions and periodic transactions.

Bug

Even though the interval part is optional as per the doc, there is a bug in the ledger-cli, so you can't use ~ in 2023/08/01, instead you always have to specify some interval like ~ Monthly in 2023/08/01.

Now you can see that you will have 5k left in your checking account at the end of the month, if you spend as per your budget. Before you spend, you can check your budget and verify if you have money available under that category.

Let's add some real transactions.

2023/08/02 Rent\n    Expenses:Rent               15,000 INR\n    Assets:Checking\n\n2023/08/03 Transport\n    Expenses:Transport           1,000 INR\n    Assets:Checking\n\n2023/08/03 Food\n    Expenses:Food                8,500 INR\n    Assets:Checking\n\n2023/08/05 Transport\n    Expenses:Transport           2,000 INR\n    Assets:Checking\n\n2023/08/07 Transport\n    Expenses:Transport           3,000 INR\n    Assets:Checking\n\n2023/08/10 Personal\n    Expenses:Personal            4,000 INR\n    Assets:Checking\n\n2023/08/15 Insurance\n    Expenses:Insurance           10000 INR\n    Assets:Checking\n

As the month progresses, you can see how much you have spent and how much you have left. You notice that you have overspent on transport and you have missed the insurance payment. You have a budget deficit now. That means, you can't actually spend as per your budget. You have to first bring the deficit back to 0. Let's cut down the entertainment and clothing budget to 0

~ Monthly in 2023/08/01\n    Expenses:Rent              15,000 INR\n    Expenses:Food              10,000 INR\n    Expenses:Clothing               0 INR\n    Expenses:Entertainment          0 INR\n    Expenses:Transport          5,000 INR\n    Expenses:Personal           5,000 INR\n    Assets:Checking\n

You can go back and adjust your budget anytime. Let's move on to the next month, assuming you haven't made any further transaction.

2023/09/01 Salary\n    Income:Salary:Acme        -50,000 INR\n    Assets:Checking\n\n~ Monthly in 2023/09/01\n    Expenses:Rent              15,000 INR\n    Expenses:Food              10,000 INR\n    Expenses:Clothing           5,000 INR\n    Expenses:Entertainment      5,000 INR\n    Expenses:Transport          5,000 INR\n    Expenses:Personal           5,000 INR\n    Assets:Checking\n

You can see a new element in the UI called Rollover1. This is basically the amount you have budgeted last month, but haven't spent. This will automatically rollover to the next month. That's pretty much it.

To recap, there are just two things you need to do.

1) Create a periodic transaction at the beginning of the month when you get your salary.

2) Adjust your budget as you spend and make sure there is no deficit.

  1. If you prefer to not have rollover feature, it can be disabled in the configuration page.\u00a0\u21a9

"},{"location":"reference/bulk-edit/","title":"Bulk Edit","text":"

Paisa provides bulk transaction editor to search and modify multiple transactions at once. The interface is made of two parts:

1) Search input box allows you to narrow down the transactions you are interested in making changes

2) Bulk Edit form allows you to make changes to the narrowed down set of transactions.

"},{"location":"reference/bulk-edit/#search","title":"Search","text":""},{"location":"reference/bulk-edit/#plain","title":"Plain","text":"

Paisa provides a powerful search query interface. Let's start with a few example queries.

Expenses:Utilities:Electricity\n

This will search for all transactions that have a posting with account named Expenses:Utilities:Electricity. By default, the search is case insensitive and will do a substring match. So, Expenses:Utilities will match Expenses:Utilities:Electricity account as well. If you want to search an account name which has special characters like space in it, you can use double quotes to enclose it like \"Expenses:Utilities:Hair Cut\".

You can also search on transaction date. For example, if you want to show all the transactions made on 1st Jan 2023, just type [2023-01-01]. If you want to see all made on that month, just leave out the day part [2023-01]. You can do the same with year, [2023] will show all the transactions made in 2023.

There is experimental support for natural language date. You can do queries like [last month], [last year], [this month], [lastweek], [jan 2023], etc.

Let's say you want to search by amount. You can do that by typing 42, it will show all the transactions that have a posting with that amount.

if you want to search a exact Account, you can do that using Regular Expression. Just type /^Assets:Equity:APPLE$/, you can also do case insensitive search by using the modifier i like /^Assets:Equity:APPLE$/i.

"},{"location":"reference/bulk-edit/#property","title":"Property","text":"

You can also search based on properties like account, commodity, amount, total, filename, note, payee and date.

payee =~ /uber/i\npayee = \"Advance Tax\"\ncommodity = GOLD\ntotal > 5000\nnote = \"rebate\"\naccount = \"Expenses:Utilities:Electricity\"\ndate >= [2023-01-01]\nfilename = creditcard/2023/jan.ledger\n

The general format is property operator value. The property can be any of the following:

  • account - posting account
  • commodity - posting commodity
  • amount - posting amount
  • total - transaction total
  • filename - name of the file the transaction is in
  • note - posting or transaction note (comment)
  • payee - transaction payee
  • date - transaction date

The operator can be any of the following:

  • = equal
  • =~ regular expression match
  • < less than
  • <= less than or equal
  • > greater than
  • >= greater than or equal

Not all the combinations of property, operator and value would work, if in doubt, just try it out, the UI will show you an error if the query is not valid.

In fact, in the previous format we saw, if the property and operator is not specified and a default set is chosen based on the value type. For example, 42 will be treated as amount = 42, Expenses:Utilities will be treated as account = Expenses:Utilities, /Expenses:Utilities/i will be treated as account =~ /Expenses:Utilities/i, [2023-01] will be treated as date = [2023-01].

"},{"location":"reference/bulk-edit/#conditional","title":"Conditional","text":"

You can combine multiple property based queries using AND and OR, you can negate them using NOT

account = Expenses:Utilities AND payee =~ /uber/i\ncommodity = GOLD OR total > 5000\ndate >= [2023-01-01] AND date < [2023-04-01]\naccount = Expenses:Utilities AND payee =~ /uber/i AND (total > 5000 OR total < 1000)\n[last year] AND (payee =~ /swiggy/i OR payee =~ /phonepe/i)\ntotal < 5000 AND NOT account = Expenses:Utilities\n

If you leave out the conditional operator, it will be treated as AND. Both of the below queries are the same

account = Expenses:Utilities payee =~ /uber/i\naccount = Expenses:Utilities AND payee =~ /uber/i\n
"},{"location":"reference/bulk-edit/#bulk-edit-form","title":"Bulk Edit Form","text":"

Currently bulk edit form supports only account rename feature. More will be added later. The preview button allows you to see the changes before you save them. It will show a side by side diff of the changes.

"},{"location":"reference/changelog/","title":"Release Changelog","text":""},{"location":"reference/changelog/#063-2024-01-13","title":"0.6.3 (2024-01-13)","text":"
  • Introduce Sheets: A notepad calculator with access to your ledger
  • Remove flat option from cashflow > yearly page
  • Dockerimage now installs paisa to /usr/bin
  • Improve legends rendering on all pages
  • Allow user to cancel pdf password prompt
  • Add new warning for missing assets accounts from allocation target
  • Support hledger's balance assertion
  • Bug fixes
"},{"location":"reference/changelog/#062-2023-12-23","title":"0.6.2 (2023-12-23)","text":"
  • New logo
  • Allow goals to be reordered
  • Show goals on the dashboard page
  • Bug fixes
"},{"location":"reference/changelog/#061-2023-12-16","title":"0.6.1 (2023-12-16)","text":"
  • Add new price provider: Alpha Vantage
  • Make first day of the week configurable
  • Support ledger strict mode
  • Add user login support, go to User Accounts section in configuration page to enable it
  • Show notes associated with a transaction/posting
  • Bug fixes
"},{"location":"reference/changelog/#060-2023-12-09","title":"0.6.0 (2023-12-09)","text":"
  • Add individual account balance on goals page
  • Add keyboard shortcuts to format/save file on editor page
  • Add ability to search posting/transaction by note
  • Add option to reverse the order of generated transactions on import page
  • Add option to clear price cache
  • Bug fixes
"},{"location":"reference/changelog/#059-2023-11-26","title":"0.5.9 (2023-11-26)","text":"
  • Improve postings page
  • Add income statement page (Cash Flow > Income Statement)
  • Bug fixes
"},{"location":"reference/changelog/#058-2023-11-18","title":"0.5.8 (2023-11-18)","text":"
  • Add ability to specify rate, target date or monthly contribution to savings goal
  • Improve price page
  • Bug fixes
"},{"location":"reference/changelog/#057-2023-11-11","title":"0.5.7 (2023-11-11)","text":"
  • Add goals
  • Remove retirement page (available under goals)
  • Bug fixes
"},{"location":"reference/changelog/#breaking-changes","title":"Breaking Changes","text":"

Retirement page has been moved under goals. If you have used retirement, you need to setup a new retirement goal

"},{"location":"reference/changelog/#056-2023-11-04","title":"0.5.6 (2023-11-04)","text":"
  • Add support for Income:CapitalGains
  • Add option to control display precision
  • Add new price provider for gold and silver (IBJA India)
  • Add option to disable budget rollover
  • Bug fixes
"},{"location":"reference/changelog/#055-2023-10-07","title":"0.5.5 (2023-10-07)","text":"
  • Support account icon customization
  • Add beancount ledger client support
"},{"location":"reference/changelog/#054-2023-10-07","title":"0.5.4 (2023-10-07)","text":"
  • Add calendar view to recurring page
  • Support recurring period configuration
  • Support European number format
  • Bug fixes
"},{"location":"reference/changelog/#053-2023-09-30","title":"0.5.3 (2023-09-30)","text":"
  • Add Docker Image
  • Add Linux Application (deb package)
  • Move import templates to configuration file
  • Bug fixes
"},{"location":"reference/changelog/#breaking-changes_1","title":"Breaking Changes","text":"

User's custom import templates used to be stored in Database, which is a bad idea in hindsight. It's being moved to the configuration file. With this change, all the data in paisa.db would be transient and can be deleted and re created from the journal and configuration files without any data loss.

If you have custom template, take a backup before you upgrade and add it again via new version. If you have already upgraded, you can still get the data directly from the db file using the following query sqlite3 paisa.db \"select * from templates\";

"},{"location":"reference/changelog/#052-2023-09-22","title":"0.5.2 (2023-09-22)","text":"
  • Add Desktop app
  • Support password protected PDF on import page
  • Bug fixes
"},{"location":"reference/changelog/#breaking-changes_2","title":"Breaking Changes","text":"
  • The structure of price code configuration has been updated to make it easier to add more price provider in the future. In addition to the code, the provider name also has to be added. Refer the config documentation for more details
     type: mutualfund\n-    code: 122639\n+    price:\n+      provider: in-mfapi\n+      code: 122639\n     harvest: 365\n
"},{"location":"reference/changelog/#050-2023-09-16","title":"0.5.0 (2023-09-16)","text":"
  • Add config page
  • Embed ledger binary inside paisa
  • Bug fixes
"},{"location":"reference/changelog/#049-2023-09-09","title":"0.4.9 (2023-09-09)","text":"
  • Add search query support in transaction page
  • Spends at child accounts level would be included in the budget of parent account.
  • Fix the windows build, which was broken by the recent changes to ledger import
  • Bug fixes
"},{"location":"reference/changelog/#048-2023-09-01","title":"0.4.8 (2023-09-01)","text":"
  • Add budget
  • Add hierarchial cash flow
  • Switch from float64 to decimal
  • Bug fixes
"},{"location":"reference/changelog/#047-2023-08-19","title":"0.4.7 (2023-08-19)","text":"
  • Add dark mode
  • Add bulk transaction editor
"},{"location":"reference/commodities/","title":"Commodities","text":"

There are no restrictions on the type of commodities that can be used in Paisa. Anything like gold, mutual fund, NPS, etc can be tracked as a commodity. Few example transactions can be found below.

2019/02/18 NPS\n    Assets:Equity:NPS:SBI:E/*(1)!*/  /*(2)!*/15.9378 NPS_SBI_E/*(3)!*/ @ /*(4)!*/23.5289 INR/*(5)!*/\n    Assets:Checking\n\n2019/02/21 NPS\n    Assets:Equity:NPS:SBI:E      1557.2175 NPS_SBI_E @ 23.8406 INR\n    Assets:Checking\n\n2020/06/25 Gold\n    Assets:Gold                         40 GOLD @ 4650 INR\n    Assets:Checking\n
  1. Account name
  2. Number of units purchased
  3. Commodity Name
  4. Purchase Price per Unit
  5. Currency

Paisa comes with inbuilt support for fetching the latest price of some commodities like mutual fund, NPS, stocks, etc from few providers. For others, it will try to use the latest purchase price specified in the journal. For example, when you enter the second NPS transaction on 2019/02/21, the valuation of your existing holdings will be adjusted based on the new purchase price.

To link a commodity with a commodity price provider, Go to Configuration page and expand the Commodities section. You can click the icon to add a new one. Edit the name to commodity name. Click the icon near Price section and select the price provider details. Once done, save the configuration and click the Update Prices from the top right hand side menu. If you had done everything correctly, you would see the latest price of the commodity under Assets Balance. You can also view the full price history on Ledger Price

"},{"location":"reference/commodities/#mf-api-mutual-fund","title":"MF API Mutual Fund","text":"

To automatically track the latest value of your mutual funds holdings, you need to link the commodity and the fund scheme code.

commodities:\n  - name: NIFTY # (1)!\n    type: mutualfund # (2)!\n    price:\n        provider: in-mfapi # (3)!\n        code: 120716 # (4)!\n
  1. commodity name
  2. commodity type
  3. price provider name
  4. mutual fund scheme code

The example configuration above links nifty commodity with the respective mutual fund scheme code.

"},{"location":"reference/commodities/#yahoo","title":"Yahoo","text":"

To automatically track the latest value of your stock holdings, you need to link the commodity and the stock ticker name.

commodities:\n  - name: APPLE # (1)!\n    type: stock # (2)!\n    price:\n        provider: com-yahoo # (3)!\n        code: AAPL # (4)!\n
  1. commodity name
  2. type
  3. price provider name
  4. stock ticker code

Stock prices are fetched from yahoo finance website. The ticker code should match the code used in yahoo. If the fetched price currency is not the default currency, it will be converted to default currency using the forex rate apis.

"},{"location":"reference/commodities/#alpha-vantage","title":"Alpha Vantage","text":"

Supports 100,000+ stocks, ETFs, mutual funds etc. It also provides exchange rates, so the price can be converted to default currency if required.

commodities:\n  - name: RELIANCE # (1)!\n    type: stock # (2)!\n    price:\n        provider: co-alphavantage # (3)!\n        code: 7GAURDT55LU7OQKK:RELIANCE.BSE:INR # (4)!\n
  1. commodity name
  2. type
  3. price provider name
  4. code

Code is made of three parts, apiKey, symbol and currency. For example in 7GAURDT55LU7OQKK:RELIANCE.BSE:INR, 7GAURDT55LU7OQKK is the api key, RELIANCE.BSE is the symbol and INR is the currency. Alpha Vantage provides free api key with 25 requests per day limit.

"},{"location":"reference/commodities/#purified-bytes-nps","title":"Purified Bytes NPS","text":"

To automatically track the latest value of your nps funds holdings, you need to link the commodity and the fund scheme code.

commodities:\n  - name: NPS_HDFC_E # (1)!\n    type: nps # (2)!\n    price:\n        provider: com-purifiedbytes-nps # (3)!\n        code: SM008002 # (4)!\n
  1. commodity name
  2. type
  3. price provider name
  4. nps fund scheme code

The example configuration above links NPS fund commodity with their respective NPS fund scheme code.

"},{"location":"reference/commodities/#purified-bytes-metals","title":"Purified Bytes Metals","text":"

To automatically track the latest price of gold or silver at various level of purity, you need to link the commodity and the metal code. The price is for 1 gram of the metal.

commodities:\n  - name: GOLD # (1)!\n    type: metal # (2)!\n    price:\n        provider: com-purifiedbytes-metal # (3)!\n        code: gold-999 # (4)!\n
  1. commodity name
  2. type
  3. price provider name
  4. metal name along with purity

The following metals and purity combinations are supported.

Metal Purity Code Gold 999 gold-999 Gold 995 gold-995 Gold 916 gold-916 Gold 750 gold-750 Gold 585 gold-585 Silver 999 silver-999"},{"location":"reference/commodities/#realestate","title":"RealEstate","text":"

Some commodities like real estate are bought once and the price changes over time. Ledger allows you to set the price as on date.

2014/01/01 Home purchase\n    Assets:House                                1 APT @ 4000000 INR\n    Liabilities:Homeloan\n\nP 2016/01/01 00:00:00 APT 5000000 INR\nP 2018/01/01 00:00:00 APT 6500000 INR\nP 2020/01/01 00:00:00 APT 6700000 INR\nP 2021/01/01 00:00:00 APT 6300000 INR\nP 2022/01/01 00:00:00 APT 8000000 INR\n
"},{"location":"reference/commodities/#currencies","title":"Currencies","text":"

If you need to deal with multiple currencies, just treat them as you would treat any commodity. Since paisa is a reporting tool, it will always try to convert other currencies to the default_currency. As long as the exchange rate from a currency to default_currency is available, paisa would work without issue

P 2023/05/01 00:00:00 USD 81.75 INR\n\n2023/05/01 Freelance Income\n    ;; conversion rate will be picked up\n    ;; from the price directive above\n    Income:Freelance      -100 USD\n    Assets:Checking\n\n2023/06/01 Freelance Income\n    ;; conversion rate is specified inline\n    Income:Freelance      -200 USD @ 82.75 INR\n    Assets:Checking\n\n2023/07/01 Netflix\n    ;; if not available for a date,\n    ;; will use previous known conversion rate (82.75)\n    Expenses:Entertainment  10 USD\n    Assets:Checking\n
"},{"location":"reference/commodities/#update","title":"Update","text":"

Paisa fetches the latest price of the commodities only when you update the prices. This can be done via UI using the dropdown in the top right hand side corner or via paisa update command. Make sure to update the prices after you make any changes to your journal file or you want to fetch the latest value of the commodities.

"},{"location":"reference/config/","title":"Configuration","text":"

All the configuration related to paisa is stored in a yaml file named paisa.yaml. The configuration can be edited via the web interface. The sequence in which paisa looks for the file is described below

  1. PAISA_CONFIG environment variable
  2. via --config flag
  3. Current working directory
  4. paisa/paisa.yaml file inside User Documents folder.

If it can't find the configuration file, it will create a default configuration file named paisa/paisa.yaml inside User Documents folder. The default configuration is tuned for Indians, users from other countries would have to change the default_currency and locale.

"},{"location":"reference/config/#accounts","title":"Accounts","text":"

In many places, paisa expects you to specify a list of accounts. You can type the full account name like Account:Equity:APPL. Paisa also supports wildcard *, you can use Account:Equity:* to represent all accounts under Equity. It's also possible to use negation. !Expenses:Tax will match all accounts except Tax. If you use negation, then all the accounts should be negation. Don't mix negation with others, if done the behavior will be undefined.

# Path to your journal file. It can be absolute or relative to the\n# configuration file. The main journal file can refer other files using\n# `include` as long as all the files are in the same or sub directory\n# REQUIRED\njournal_path: /home/john/Documents/paisa/main.ledger\n\n# Path to your database file. It can be absolute or relative to the\n# configuration file. The database file will be created if it does not exist.\n# REQUIRED\ndb_path: /home/john/Documents/paisa/paisa.db\n\n# The ledger client to use\n# OPTIONAL, DEFAULT: ledger, ENUM: ledger, hledger, beancount\nledger_cli: ledger\n\n# The default currency to use. NOTE: Paisa tries to convert other\n# currencies to default currency, so make sure it's possible to\n# convert to default currency by specifying the exchange rate.\n#\n# OPTIONAL, DEFAULT: INR\ndefault_currency: INR\n\n# The locale used to format numbers. The list of locales supported\n# depends on your browser. It's known to work well with en-US and en-IN.\n#\n# OPTIONAL, DEFAULT: en-IN\nlocale: en-IN\n\n# First month of the financial year. This can be set to 1 to follow\n# January to December.\n#\n# OPTIONAL, DEFAULT: 4\nfinancial_year_starting_month: 4\n\n# First day of the week. This can be set to 1 to follow Monday to\n# Sunday. 0 represents Sunday, 1 represents Monday and so on.\n#\n# OPTIONAL, DEFAULT: 0\nweek_starting_day: 0\n\n# When strict mode is enabled, all the accounts and commodities should\n# be defined before use. This is same as --pedantic flag in ledger and\n# --strict flag in hledger. Doesn't apply to beancount.\n#\n# OPTIONAL, ENUM: yes, no DEFAULT: no\nstrict: \"no\"\n\n## Budget\nbudget:\n  # Rollover unspent money to next month\n  # OPTIONAL, ENUM: yes, no DEFAULT: yes\n  rollover: \"yes\"\n\n## Goals\ngoals:\n  # Retirement goals\n  retirement:\n      # Goal name\n      # REQUIRED\n    - name: Retirement\n      # Goal icon\n      # REQUIRED\n      icon: mdi:palm-tree\n      # Safe Withdrawal Rate\n      # OPTIONAL, DEFAULT: 4\n      swr: 2\n      # List of expense accounts\n      # OPTIONAL, DEFAULT: Expenses:*\n      expenses:\n        - Expenses:Clothing\n        - Expenses:Education\n        - Expenses:Entertainment\n        - Expenses:Food\n        - Expenses:Gift\n        - Expenses:Insurance\n        - Expenses:Misc\n        - Expenses:Restaurant\n        - Expenses:Shopping\n        - Expenses:Utilities\n      # List of accounts where you keep retirement savings\n      # OPTIONAL, DEFAULT: Assets:*\n      savings:\n        - Assets:Equity:*\n        - Assets:Debt:*\n      # By default, average of last 3 year expenses will be used to\n      # calculate your yearly expenses. This can be overridden by setting\n      # this configuration to positive value\n      # OPTIONAL, DEFAULT: 0\n      yearly_expenses: 0\n  savings:\n      # Goal name\n      # REQUIRED\n    - name: House\n      # Goal icon\n      # REQUIRED\n      icon: fluent-emoji-high-contrast:house-with-garden\n      # Goal target amount\n      # REQUIRED\n      target: 100000\n      # Goal target date\n      # OPTIONAL (either target_date or payment_per_period can be specified)\n      target_date: \"2030-01-01\"\n      # Expected rate of returns\n      # OPTIONAL\n      payment_per_period: 0\n      # Expected rate of returns\n      # OPTIONAL, REQUIRED if target_date or payment_per_period is set\n      rate: 5\n      # List of accounts where you keep the goal's savings\n      # REQUIRED\n      accounts:\n        - Assets:Equity:**\n## Schedule AL\n# OPTIONAL, DEFAULT: []\nschedule_al:\n  # Code\n  # REQUIRED, ENUM: immovable, metal, art, vehicle, bank, share,\n  # insurance, loan, cash, liability\n  - code: metal\n    accounts:\n      - Assets:Gold\n  - code: bank\n    accounts:\n      - Assets:Checking\n      - Assets:Debt:Cash:FD\n  - code: share\n    accounts:\n      - Assets:Equity:*\n  - code: insurance\n    accounts:\n      - Assets:Debt:Insurance\n\n## Allocation Target\n# OPTIONAL, DEFAULT: []\nallocation_targets:\n  - name: Debt\n    target: 30\n    accounts:\n      - Assets:Debt:*\n      - Assets:Checking\n  - name: Equity\n    target: 60\n    accounts:\n      - Assets:Equity:*\n  - name: Equity Foreign\n    target: 20\n    accounts:\n      - Assets:Equity:NASDAQ\n  - name: Equity Index\n    target: 20\n    accounts:\n      - Assets:Equity:NIFTY\n  - name: Equity Active\n    target: 20\n    accounts:\n      - Assets:Equity:PPFAS\n  - name: Others\n    target: 10\n    accounts:\n      - Assets:Gold\n      - Assets:RealEstate\n\n## Commodities\n# OPTIONAL, DEFAULT: []\ncommodities:\n  - name: NASDAQ\n    # Required, ENUM: mutualfund, stock, nps, unknown\n    type: mutualfund\n    price:\n      # Required, ENUM: in-mfapi, com-yahoo, com-purifiedbytes-nps, co-alphavantage\n      provider: in-mfapi\n      # differs based on provider\n      code: 145552\n    harvest: 1095\n    # Optional, ENUM: equity65, equity35, debt, unlisted_equity\n    tax_category: debt\n  - name: NIFTY\n    type: mutualfund\n    price:\n      provider: in-mfapi\n      code: 120716\n    harvest: 365\n    tax_category: equity65\n  - name: APPLE\n    type: stock\n    price:\n      provider: com-yahoo\n      code: AAPL\n    harvest: 1095\n    tax_category: equity65\n\n## Import Templates\n# OPTIONAL, DEFAULT: []\nimport_templates:\n  - name: SBI Account Statement\n    # Required\n    content: |\n      {{#if (isDate ROW.A \"D MMM YYYY\")}}\n        {{date ROW.A \"D MMM YYYY\"}} {{ROW.C}}\n        {{#if (isBlank ROW.F)}}\n          {{predictAccount prefix=\"Expenses\"}}      {{amount ROW.E}} INR\n          Assets:Checking:SBI\n        {{else}}\n          Assets:Checking:SBI                       {{amount ROW.F}} INR\n          {{predictAccount prefix=\"Income\"}}\n        {{/if}}\n      {{/if}}\n    # Should be a valid handlebar template\n\n## Accounts: account customization\n# OPTIONAL, DEFAULT: []\naccounts:\n  - name: Liabilities:CreditCard:IDFC\n    # Required, name of the account\n    icon: arcticons:idfc-first-bank\n    # Optional, use the UI to select the icon.\n\n## List of user accounts.\n# If the list is empty, then no authentication will be performed\n#\n# OPTIONAL, DEFAULT: []\nuser_accounts:\n  - username: john.doe\n    # Required\n    password: sha256:a96dc73edd639b1c711b006e714bd2ff5bf5c1aecd77d0b3c3370403c66d58e5\n    # Required, password hashed twice with sha256, then prefixed sha256:\n    # echo -n 'secret' | sha256sum | head -c 64 | sha256sum | head -c 64\n
"},{"location":"reference/editor/","title":"Editor","text":"

Paisa uses codemirror that comes with a standard set of keyboard shortcuts. In addition to that, Paisa has few more shortcuts, which are listed below.

"},{"location":"reference/editor/#keyboard-shortcuts","title":"Keyboard shortcuts","text":"Linux Mac Windows Description Ctrl+S Ctrl+S Ctrl+S Save file Ctrl+Shift+I Ctrl+Shift+I Ctrl+Shift+I Prettify Ctrl+F Cmd+F Ctrl+F Open search panel Ctrl+Z Cmd+Z Ctrl+Z Undo Ctrl+Y Cmd+Y Ctrl+Y Redo"},{"location":"reference/import/","title":"Import","text":"

Paisa provides ability to convert CSV, TXT, XLS, XLSX or PDF files to Ledger file format. The import page is made of three components.

Experimental

PDF support is in an experimental stage and may not accurately detect rows.

1) File Preview - You can drag and drop files here to preview the contents.

2) Ledger Preview - This is where the converted ledger file will be shown.

3) Template Editor - This is where you can edit the template.

Each row in the CSV file is converted to a transaction in the ledger. This conversion is controlled by the template.

{{#if (and (isDate ROW.A \"DD/MM/YYYY\") (isBlank ROW.G))}}\n {{date ROW.A \"DD/MM/YYYY\"}} {{ROW.C}}\n    {{predictAccount prefix=\"Expenses\"}}        {{ROW.F}} INR\n    Assets:Checking\n{{/if}}\n

Let's break this down. The first line is a conditional statement. It checks if the row has a date in the first column. You can refer any column using their alphabets. The second line constructs the transaction header. The third line constructs the first posting. The fourth line constructs the second posting.

Effectively a single row in the CSV file is converted to a single transaction like this.

2023/03/28 AMAZON HTTP://WWW.AM IN\n    Expenses:Shopping       249.00 INR\n    Assets:Checking\n

The template is written in Handlebars. Paisa provides a few helper functions to make it easier to write the template.

"},{"location":"reference/import/#template-management","title":"Template Management","text":"

Paisa ships with a few built-in templates. You can also create your own. To create a new template, edit the template and click on the Save As button. User defined custom templates are stored in the configuration file.

Tip

The import system is designed to be extensible and might not be intuitive if you are not accustomed to coding. If you are unable to create a template suitable for your file, please open an issue with a sample file, and we will provide assistance, possibly adding it to the built-in templates.

"},{"location":"reference/import/#template-data","title":"Template Data","text":"
  1. ROW - This is the current row being processed. You can refer to any column using their alphabets. For example, ROW.A refers to the first column, ROW.B refers to the second column and so on. The current row index is available as ROW.index.
Example
{\n  \"A\": \"28/03/2023\",\n  \"B\": \"7357680821\",\n  \"C\": \"AMAZON HTTP://WWW.AM IN\",\n  \"D\": \"12\",\n  \"E\": \"0\",\n  \"F\": \"249.00\",\n  \"G\": \"\",\n  \"index\": 6\n}\n
  1. SHEET - This is the entire sheet. It is an array of rows. You can refer a specific cell using the following syntax SHEET.5.A.
Example
[\n    {\n        \"A\": \"Accountno:\",\n        \"B\": \"49493xxx003030\",\n        \"index\": 0\n    },\n    {\n        \"A\": \"Customer Name:\",\n        \"B\": \"MR John Doe\",\n        \"index\": 1\n    },\n    {\n        \"A\": \"Address:\",\n        \"B\": \"1234, ABC Street, XYZ City, 123456\",\n        \"index\": 2\n    },\n    {\n        \"A\": \"Transaction Details:\",\n        \"index\": 3\n    },\n    {\n        \"A\": \"Date\",\n        \"B\": \"Sr.No.\",\n        \"C\": \"Transaction Details\",\n        \"D\": \"Reward Point Header\",\n        \"E\": \"Intl.Amount\",\n        \"F\": \"Amount(in Rs)\",\n        \"G\": \"BillingAmountSign\",\n        \"index\": 4\n    },\n    {\n        \"A\": \"49493xxx003030\",\n        \"index\": 5\n    },\n    {\n        \"A\": \"28/03/2023\",\n        \"B\": \"7357680821\",\n        \"C\": \"AMAZON HTTP://WWW.AM IN\",\n        \"D\": \"12\",\n        \"E\": \"0\",\n        \"F\": \"249.00\",\n        \"G\": \"\",\n        \"index\": 6\n    },\n    {\n        \"A\": \"28/03/2023\",\n        \"B\": \"7357821997\",\n        \"C\": \"AMAZON HTTP://WWW.AM IN\",\n        \"D\": \"28\",\n        \"E\": \"0\",\n        \"F\": \"575.00\",\n        \"G\": \"\",\n        \"index\": 7\n    }\n]\n
"},{"location":"reference/import/#template-helpers","title":"Template Helpers","text":""},{"location":"reference/import/#eqa-any-b-any-boolean","title":"eq(a: any, b: any): boolean","text":"

Checks if the two values are equal.

"},{"location":"reference/import/#notvalue-any-boolean","title":"not(value: any): boolean","text":"

Negates the given value.

"},{"location":"reference/import/#andargs-any-boolean","title":"and(...args: any[]): boolean","text":"

Returns true if all the arguments are true.

"},{"location":"reference/import/#orargs-any-boolean","title":"or(...args: any[]): boolean","text":"

Returns true if any of the arguments are true.

"},{"location":"reference/import/#gtea-string-number-b-string-number-boolean","title":"gte(a: string | number, b: string | number): boolean","text":"

Checks if a is greater than or equal to b.

"},{"location":"reference/import/#gta-string-number-b-string-number-boolean","title":"gt(a: string | number, b: string | number): boolean","text":"

Checks if a is greater than b.

"},{"location":"reference/import/#ltea-string-number-b-string-number-boolean","title":"lte(a: string | number, b: string | number): boolean","text":"

Checks if a is less than or equal to b.

"},{"location":"reference/import/#lta-string-number-b-string-number-boolean","title":"lt(a: string | number, b: string | number): boolean","text":"

Checks if a is less than b.

"},{"location":"reference/import/#negatevalue-string-number-number","title":"negate(value: string | number): number","text":"

Negates the given value. For example, negate(\"123.45\") will return -123.45

"},{"location":"reference/import/#amountstr-string-default-string-string","title":"amount(str: string, {default?: string}): string","text":"

Converts the given string to a valid amount. If the string is blank, the default value is used. Examples (0.9534) to -0.9534, \u20b9 1,234.56 to 1234.56

"},{"location":"reference/import/#roundstr-string-precision-number-number","title":"round(str: string, {precision?: number}): number","text":"

Rounds the given value to the given precision. If precision is not set, defaults to 0

"},{"location":"reference/import/#isdatestr-string-format-string-boolean","title":"isDate(str: string, format: string): boolean","text":"

Checks if the given string is a valid date in the given format. Refer Day.js for the full list of supported formats.

"},{"location":"reference/import/#predictaccountterms-string-prefix-string-string","title":"predictAccount(...terms: string[], {prefix?: string}): string","text":"

Helps with prediction of account name to be used in a transaction. Let's say you import your Credit Card bill, you would prefer the system to automatically assign the account name for you. predictAccount acts like a search engine. It will try to find a transaction that is similar to the current transaction. The search requires input (referred as terms) and it will match transactions with similar description and will pick the accounts from the top match.

If terms are not provided, the entire ROW will be used.

The prefix is optional and will be used to filter out matching accounts. If no match is found, Unknown will be returned.

{{predictAccount prefix=\"Income\"}}\n{{predictAccount ROW.C ROW.F prefix=\"Income\"}}\n

Tip

Prediction will only work if you have similar transactions in ledger file. It usually means, first time you have to manually fix the Unknown account and then subsequent imports will work

"},{"location":"reference/import/#isblankstr-string-boolean","title":"isBlank(str: string): boolean","text":"

Checks if the given string is blank.

"},{"location":"reference/import/#datestr-string-format-string-string","title":"date(str: string, format: string): string","text":"

Parses the given string as a date in the given format and returns the date in the format YYYY/MM/DD. Refer Day.js for the full list of supported formats.

"},{"location":"reference/import/#findabovecolumn-string-regexp-string-string","title":"findAbove(column: string, {regexp?: string}): string","text":"

Finds the first cell above the current row in the given column. If regexp is provided, the search will continue till a match is found

{{findAbove B regexp=\"LIMITED\"}}\n
"},{"location":"reference/import/#findbelowcolumn-string-regexp-string-string","title":"findBelow(column: string, {regexp?: string}): string","text":"

Finds the first cell below the current row in the given column. If regexp is provided, the search will continue till a match is found

{{findBelow B regexp=\"LIMITED\"}}\n
"},{"location":"reference/import/#acronymstr-string-string","title":"acronym(str: string): string","text":"

Returns the acronym of the given string that is suitable to be used as a commodity symbol. For example, UTI Nifty Next 50 Index Growth Direct Plan will be converted to UNNI

"},{"location":"reference/import/#replacestr-string-search-string-replace-string-string","title":"replace(str: string, search: string, replace: string): string","text":"

Trims the given string.

"},{"location":"reference/import/#regexpteststr-string-regexp-string-boolean","title":"regexpTest(str: string, regexp: string): boolean","text":"

Tests the given string against the given regular expression.

"},{"location":"reference/import/#regexpmatchstr-string-regexp-string-group-number-string","title":"regexpMatch(str: string, regexp: string, {group?: number}): string","text":"

Extract part of a string. Let's say you have Axis Long Term Equity Growth Direct Plan and you want to extract Axis Long Term Equity, you can use {{regexpMatch ROW.C \"(.*) Growth Direct Plan\" group=1}} assuming the string is in the column C. group is optional and defaults to 0.

"},{"location":"reference/import/#textrangefromcolumn-string-tocolumn-string-separator-number-string","title":"textRange(fromColumn: string, toColumn: string, {separator?: number}): string","text":"

Extracts text from the given range of columns. The separator is optional and defaults to \" \".

{{textRange A C separator=\" \"}}\n
"},{"location":"reference/import/#tolowercasestr-string-string","title":"toLowerCase(str: string): string","text":"

Converts the given string to lower case.

"},{"location":"reference/import/#touppercasestr-string-string","title":"toUpperCase(str: string): string","text":"

Converts the given string to upper case.

"},{"location":"reference/import/#matchstr-string-string-string-string","title":"match(str: string, {[string]: string}): string","text":"

Let's say you are trying to import your Credit Card bill and you want map the transaction to a specific expense account based on the description. You can use the match helper to do that. The helper takes a string and a map of key value pairs. The key is the account to be returned if the string matches the value. The value must be a valid regular expression.

{{match ROW.C Expenses:Shopping=\"Amazon|Flipkart\" Expenses:Groceries=\"BigBasket\"}}\n

In case of no match null will be returned. You can combine this with or helper to return a default account.

{{or (match ROW.C Expenses:Shopping=\"Amazon|Flipkart\" Expenses:Groceries=\"BigBasket\")\n     \"Expenses:Unknown\"}}\n
"},{"location":"reference/journal/","title":"Journal","text":"

All your transactions are stored in plain text files called journal. You can organize your transactions into multiple journal files. The journal_path configuration refers your main journal file. The main journal file can refer other journal files using include directive. The include directive supports wildcards * as well. Transactions are sourced only from the main journal file and other journal files included from the main journal file.

include investments.ledger\ninclude expenses/*.ledger\n
"},{"location":"reference/journal/#editor","title":"Editor","text":"

Paisa comes with a journal editor. It allows you to edit all the files with the same file extension as your main journal and in the same or sub directories as your main journal.

"},{"location":"reference/journal/#backup","title":"Backup","text":"

Paisa tries its best to keep your journal safe. It creates a backup of your journal file every time you save it. The backup file is created with the same name as your journal file with a .backup.{timestamp} extension. You can revert back to old versions of your journal file via the editor. You can also delete the backup files from the editor.

Warning

It is recommended to keep your journal files and paisa.yaml under version control or other backup mechanism. Paisa's backup mechanism is not a replacement for a proper backup. You can ignore paisa.db file from your version control system, the data in db file can be recreated from your journal files.

"},{"location":"reference/journal/#syntax","title":"Syntax","text":"

The journal syntax of the features you use normally along with paisa is documented here. Refer ledger documentation for more details.

"},{"location":"reference/journal/#transaction","title":"Transaction","text":"
2022/01/01 Salary\n    Income:Salary:Acme      -100,000 INR\n    Assets:Checking          100,000 INR\n

A transaction should start with a date followed by description. Following that you can have 2 or more postings. The posting line should have at least 2 leading spaces. The account name and the amount should be separated by at least 2 spaces.

"},{"location":"reference/journal/#commodity","title":"Commodity","text":"
2022/01/07 Investment\n    Assets:Checking         -20,000 INR\n    Assets:Equity:NIFTY   168.690 NIFTY @ 118.56 INR\n

commodity cost can be specified using the @ syntax. Here 118.56 is the per unit cost and 168.690 is the quantity you have bought.

"},{"location":"reference/journal/#comment","title":"Comment","text":"
2023/07/01 Rent\n    ; This is a transaction comment\n    Expenses:Rent             15,000 INR\n    Assets:Checking   ; This is a posting comment\n

Any text after ; is treated as a comment. Comment can be at whole transaction level or individual posting level. Comment is also referred as note in many places, both are same.

"},{"location":"reference/journal/#tags","title":"Tags","text":"
2023/07/01 Rent\n    ; Recurring: Rent\n    Expenses:Rent             15,000 INR\n    Assets:Checking\n

Transactions can be tagged with extra metadata called tags. Tag has two parts: tag name and value. In the above example, Recurring is the name and Rent is the value. Tag should be inside comment.

"},{"location":"reference/journal/#include","title":"Include","text":"
include investments.ledger\ninclude expenses/*.ledger\n

Include directive can be used to include other journal files. It supports wildcards *.

"},{"location":"reference/ledger-cli/","title":"Ledger CLI","text":"

Paisa is compatible with ledger, hledger and beancount. By default paisa will try to use ledger, if you prefer to use hledger or beancount instead, change the ledger_cli value in paisa.yaml

# OPTIONAL, DEFAULT: ledger, ENUM: ledger, hledger, beancount\nledger_cli: hledger\n

Paisa ships with ledger binary. If you use hledger or beancount, make sure that the binaries are installed.

"},{"location":"reference/ledger-cli/#unavailable-features","title":"Unavailable Features","text":"

Some of the features that are available in Paisa are not supported by hledger and beancount

"},{"location":"reference/ledger-cli/#hledger","title":"hledger","text":"
  • Recurring (partial) - hledger supports automated transactions, but it doesn't allow to add only metadata to transaction. So some of the examples in the recurring section will not work with hledger. It's possible to add metadata to transactions manually.
"},{"location":"reference/ledger-cli/#beancount","title":"beancount","text":"
  • Budget - budget is based on periodic transactions that is no supported by beancount.

  • Recurring (partial) - beancount doesn't support automated transactions. It's possible to add metadata to transactions manually. Use lowercase for tag name.

  • Search filter in Transactions and Postings pages doesn't support note property.

"},{"location":"reference/recurring/","title":"Recurring","text":"

Some of the transactions recur on a regular interval and it might be useful to know the next due date for such transactions. Recurring page shows the upcoming or recently missed transactions.

Paisa depends on the posting metadata to identify which transactions are recurring. This metadata can be added in couple of ways. Let's say you pay rent every month and you want to mark it as recurring, a typical journal would like below

2023/07/01 Rent\n    Expenses:Rent             15,000 INR\n    Assets:Checking\n\n2023/08/01 Rent\n    Expenses:Rent             15,000 INR\n    Assets:Checking\n

You can manually tag a posting by adding ; Recurring: Rent.

2023/07/01 Rent\n    ; Recurring: Rent\n    Expenses:Rent             15,000 INR\n    Assets:Checking\n\n2023/08/01 Rent\n    ; Recurring: Rent\n    Expenses:Rent             15,000 INR\n    Assets:Checking\n

The first part of the metadata before the colon is called tag name. It should be Recurring. The second part is the tag value. This value is used to group transactions.

Tagging each and every posting can be tiresome. Ledger has a feature called Automated Transaction which can make this process simpler.

= Expenses:Rent\n    ; Recurring: Rent\n

The first line is the predicate and the line below it will get added to any matching posting. By default, it will match the posting account name. But you can target other attributes like payee, amount etc. You can find more examples below, more info about predicate is available on Ledger docs

= expr payee=~/^PPF$/\n    ; Recurring: PPF\n\n= expr payee=~/Mutual Fund/\n    ; Recurring: Mutual Fund\n\n= expr 'account=~/Expenses:Insurance/ and (payee=~/HDFC/)'\n    ; Recurring: Life Insurance\n\n= expr 'account=~/Expenses:Insurance/ and !(payee=~/HDFC/)'\n    ; Recurring: Bike Insurance\n\n= expr payee=~/Savings Interest/\n    ; Recurring: Savings Interest\n

Tip

Include the automated transactions at the top of the main ledger file. Ledger will apply the rules only to transactions that follow the automated transactions.

"},{"location":"reference/recurring/#period","title":"Period","text":"

Paisa will try to infer the recurring period of the transactions automatically, but this might not be perfect. Recurring period can also be explicitly specified via metadata.

= expr payee=~/Savings Interest/\n    ; Recurring: Savings Interest\n    ; Period: L MAR,JUN,SEP,DEC ?\n

Let's say your bank deposits the interest on the last day of the last month of the quarter, we can specify like the example above. Paisa editor recognizes period syntax and shows the upcoming 3 schedules right next to period metadata.

\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 day of the month 1-31\n\u2502  \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 month 1-12 or JAN-DEC\n\u2502  \u2502  \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 day of the week 0-6 (Sunday to Saturday)\n\u2502  \u2502  \u2502\n1  *  ?\n

The syntax of the period is similar to cron, with the omission of seconds and hours.

Field Allowed values Special characters Day of month 1\u201331 * , - ? L W Month 1-12 or JAN-DEC * , - Day of week 0-6 or SUN-SAT * , - ? L

* also known as wildcard represents all valid values. ? means you want to omit the field, usually you use it on the day of month or day of week. L means last day of the month or week. , can be used to specify multiple entries. - can be used to specify range. W means the closest business day to given day of month

Multiple cron expressions can be specified by joining them using |. Refer the wikipedia for more information. If you are not sure, just type it out and the editor will show you whether it is valid and the next 3 schedules if valid.

"},{"location":"reference/recurring/#examples","title":"Examples","text":"
  • Last day of every month ; Period: L * ?
  • 5th every month ; Period: 5 * ?
  • Every Sunday ; Period: ? * 0
  • 1st of Jan and 7th of Feb ; Period: 1 JAN ? | 7 FEB ?
  • Closest business day to the 15th day of every month. ; Period: 15W * ?

Warning

Recurring page will only display a transaction as recurring if there is more than one transaction with the same tag name. If you have only one transaction, wait untill the next transaction is added to see it on the recurring page.

"},{"location":"reference/sheets/","title":"Sheets","text":""},{"location":"reference/sheets/#introduction","title":"Introduction","text":"

Sheet is a notepad calculator that computes the answer as you type. It has full access to your ledger and can be used to calculate the answers for a wide variety of financial questions.

Experimental

Sheet is an experimental feature. Give it a try and let me know how it goes, specially what is missing and what can be improved. The syntax and semantics of sheet may change in future releases.

"},{"location":"reference/sheets/#calculator","title":"Calculator","text":"

Sheet can act as a normal calculator. The example below shows how to calculate the monthly EMI for a home loan.

# Home Loan\nprice = 40,00,000\ndown_payment = 20% * price\nfinance_amount = price - down_payment\ninterest_rate = 8.6%\nterm = 30\n\nn = term * 12\nr = interest_rate / 12\n# EMI\nmonthly_payment = r / (1 - (1 + r) ^ (-n)) * finance_amount\n
# Home Loan\n40,00,000\n8,00,000\n32,00,000\n0\n30\n\n360\n0\n# EMI\n24832\n
"},{"location":"reference/sheets/#function","title":"Function","text":"

Sheets comes with a set of built-in functions. You can also define your own functions. The example below shows how to define a function

# Years to Double\nyears_to_double(rate) = 72 / rate\n\nyears_to_double(2)\nyears_to_double(4)\nyears_to_double(6)\nyears_to_double(8)\nyears_to_double(10)\nyears_to_double(12)\nyears_to_double(14)\n
# Years to Double\n\n\n36\n18\n12\n9\n7\n6\n5\n
"},{"location":"reference/sheets/#query","title":"Query","text":"

Query is what makes sheets powerful. It allows you to query your ledger postings and do calculations on them. The example below shows how to calculate cost basis of your assets so you can report them to Income Tax department.

# Schedule AL\ndate_query = {date <= [2023-03-31]}\ncost_basis(x) = cost(fifo(x AND date_query))\ncost_basis_negative(x) = cost(fifo(negate(x AND date_query)))\n\n# Immovable\nimmovable = cost_basis({account = Assets:House})\n\n# Movable\nmetal = 0\nart = 0\nvehicle = 0\nbank = cost_basis({account = /^Assets:Checking/})\nshare = cost_basis({account =~ /^Assets:Equity:.*/ OR\n                    account =~ /^Assets:Debt:.*/})\ninsurance = 0\nloan = 0\ncash = 0\n\n# Liability\nliability = cost_basis_negative({account =~ /^Liabilities:Homeloan/})\n\n# Total\ntotal = immovable + metal + art + vehicle + bank + share + insurance + loan + cash - liability\n
# Schedule AL\n\n\n\n\n# Immovable\n25,00,000\n\n# Movable\n0\n0\n0\n1,21,402\n66,98,880\n\n0\n0\n0\n\n# Liability\n6,21,600\n\n# Total\n86,98,682\n
"},{"location":"reference/sheets/#syntax","title":"Syntax","text":""},{"location":"reference/sheets/#number","title":"Number","text":"

Sheet allows comma as a separator. % is a syntax sugar for dividing the number by 100. So 8% is same as 0.08.

100,00\n100.00\n-100\n8%\n
"},{"location":"reference/sheets/#operators","title":"Operators","text":"

Sheet supports the following operators. ^ is the exponentiation operator.

1 + 1\n1 - 1\n1 * 1\n1 / 1\n1 ^ 2\n
"},{"location":"reference/sheets/#variable","title":"Variable","text":"

You can define variables using = operator. Variables have to be defined before they are used.

x = 1\ny = 2\n\nz = x + y\n
"},{"location":"reference/sheets/#function_1","title":"Function","text":"

Sheet comes with a set of built-in functions. You can also define your own functions. Function definition starts with the function name and then a list of arguments. The body of the function is a single expression. To call a function, use the function name followed by arguments.

sum(a, b) = a + b\n\nsum(1, 2)\n
"},{"location":"reference/sheets/#query_1","title":"Query","text":"

Query is a first class citizen in sheet. You can think of a query as a list of postings that match the conditions. The query syntax is same as the search syntax used in postings and transactions pages. It has to be enclosed inside a {}. Query can be treated as any other value, can be passed as an argument, can be assigned to a variable. In fact you can combine two queries using AND and OR operator as well.

query = {account = Expenses:Utilities AND payee =~ /uber/i}\n\nupto_this_fy = {date < [2024-04-01]}\nassets = { account =~ /^Assets:.*/ }\nliabilities = { account =~ /^Liabilities:.*/ }\n\nassets_upto_this_fy = upto_this_fy AND assets\nliabilities_upto_this_fy = upto_this_fy AND liabilities\n
What is posting?

2022/01/01 Salary\n    Income:Salary:Acme        -100,000 INR\n    Assets:Checking            100,000 INR\n
In the above transaction, there are two postings. A transaction consists of several postings that sum to zero. If you want to know the cost of your checking account, you would use cost({account = Assets:Checking})

"},{"location":"reference/sheets/#comment","title":"Comment","text":"

Sheet supports single line comments starting with ; or //.

// set x\nx = 1\n; set y\ny = 2\n\nz = x + y // add x and y\n
"},{"location":"reference/sheets/#functions","title":"Functions","text":"

You can find the full list of built-in functions here. This list is very slim as of now, please start a discussion if you want some functions to be added here.

"},{"location":"reference/sheets/#costq-posting-query-number","title":"cost(q: Posting[] | Query): number","text":"

Returns the sum of the cost of all the postings.

"},{"location":"reference/sheets/#balanceq-posting-query-number","title":"balance(q: Posting[] | Query): number","text":"

Returns the sum of the current market value of all the postings.

"},{"location":"reference/sheets/#fifoq-posting-query-posting","title":"fifo(q: Posting[] | Query): Posting[]","text":"

Returns the list of postings after performing a FIFO adjustment. For example, assume you have 3 postings

2020/01/01 Buy\n    Assets:Bank:Checking   100 USD\n2020/02/01 Buy\n    Assets:Bank:Checking   100 USD\n2020/03/01 Sell\n    Assets:Bank:Checking   -50 USD\n

after FIFO adjustment, you will get the following postings

2020/01/01 Buy\n    Assets:Bank:Checking    50 USD\n2020/02/01 Buy\n    Assets:Bank:Checking   100 USD\n

All your sell postings will be adjusted against the oldest buy postings and you will have the remaining buy postings.

"},{"location":"reference/sheets/#negateq-posting-query-posting","title":"negate(q: Posting[] | Query): Posting[]","text":"

Negates the amount and quantity of all the postings. This would be useful when you want to do some calculation on liabilities or income which are negative in nature.

"},{"location":"reference/user-authentication/","title":"User Authentication","text":"

You can setup username and password to make sure only you can access the application. Go to Configuration page and expand the User Accounts section. You can click the icon to add a new username and password. Once you save the configuration, you will get logged out if you had not logged in earlier via another account.

It is important to understand that authentication only protects the application user interface. If someone can access your computer and they can access the folder where Paisa stores the ledger and database files, they will be able to view your data.

"},{"location":"reference/user-authentication/#implementation-details","title":"Implementation details","text":"

Paisa uses cryptographic hash function sha-256 to convert your password to digest before storing it in the configuration file. This has few implications. No one can look at the configuration file and get the password, this includes you as well. If you forget the password, you can remove the user accounts from configuration file to get back access.

Warning

If you run paisa on a server and access it over public internet, make sure to use it over https and use a strong password. If you run it over plain http, man in the middle attack can be performed to obtain the data including your password.

"},{"location":"reference/goals/","title":"Goals","text":"

Goal helps you track your financial objective and progress. You can create a goal for any financial objective you have, such as saving for a vacation, or building an emergency fund or planning for retirement.

Paisa currently supports two types of goals:

  1. Retirement
  2. Savings

More goal types will be added in the future. Feel free to create a discussion if you have any suggestions.

"},{"location":"reference/goals/#create-goal","title":"Create Goal","text":"

To add a new goal, go to the Configuration page and expand the goals section. You would see a list of goal types. Expand the type you want to add and click on the icon to add a new goal. The configuration details are available in the respective goal type pages.

Under Development

Goals is currently under development and you might see changes with every new release. If you want to share feedback, this is a good time to do so.

"},{"location":"reference/goals/retirement/","title":"Retirement","text":"

Paisa will help you plan your retirement and track your progress. The first part is figuring out what should be your retirement corpus. This will be your target. Instead of specifying the amount explicitly, you can specify your expected yearly expenses and the safe withdrawal rate.

goals:\n  retirement:\n    - name: Retirement\n      icon: mdi:palm-tree\n      swr: 3.3\n      yearly_expenses: 1100000\n

If you use paisa to track expenses, instead of specifying the yearly_expenses, you can specify the list of accounts. Paisa will take the average of the last 3 year expenses

goals:\n  retirement:\n    - name: Retirement\n      icon: mdi:palm-tree\n      swr: 2\n      expenses:\n        - Expenses:Entertainment\n        - Expenses:Gift\n        - Expenses:Insurance\n        - Expenses:Misc\n        - Expenses:Shopping\n        - Expenses:Utilities\n

Now that the target is specified, you need to specify the list of accounts where you keep your retirement savings.

goals:\n  retirement:\n    - name: Retirement\n      icon: mdi:palm-tree\n      swr: 2\n      expenses:\n        - Expenses:Entertainment\n        - Expenses:Gift\n        - Expenses:Insurance\n        - Expenses:Misc\n        - Expenses:Shopping\n        - Expenses:Utilities\n      savings:\n        - Assets:Equity:*\n        - Assets:Debt:*\n
"},{"location":"reference/goals/savings/","title":"Savings","text":"

Savings represents a general financial objective that you want to achieve, like buying a car, or a house, or a vacation.

goals:\n  savings:\n    - name: House\n      target: 5000000\n      icon: fluent-emoji-high-contrast:house-with-garden\n      accounts:\n        - Assets:Equity:*\n        - Assets:Debt:*\n

Specify the target amount, and the accounts that you keep the money in.

"},{"location":"reference/goals/savings/#forecast","title":"Forecast","text":"

When you save towards an objective, you will have a target date in mind. In the below config, you are specifying the target date and rate. Paisa will calculate the monthly contribution required to achieve the goal.

goals:\n  savings:\n    - name: House\n      target: 5000000\n      target_date: 2030-05-01\n      rate: 10\n      icon: fluent-emoji-high-contrast:house-with-garden\n      accounts:\n        - Assets:Equity:*\n        - Assets:Debt:*\n

If on the other hand, you know how much you can afford to save every month, but want to know when the goal will be achieved, you can specify the payment per period and the rate. Paisa will calculate the target date.

goals:\n  savings:\n    - name: House\n      target: 5000000\n      payment_per_period: 50000\n      rate: 10\n      icon: fluent-emoji-high-contrast:house-with-garden\n      accounts:\n        - Assets:Equity:*\n        - Assets:Debt:*\n
"},{"location":"reference/goals/savings/#math","title":"Math","text":"

This section will give some rough idea of how the calculations are done. You can skip this section if you are not interested in the math.

F V + P V \u00d7 ( 1 + R A T E ) N P E R + P M T \u00d7 ( 1 + R A T E ) N P E R \u2212 1 R A T E = 0 FV + PV \\times (1+RATE)^{NPER} + PMT \\times \\frac{(1+RATE)^{NPER} - 1}{RATE} =0

Where

Variable Description Paisa FV Future Value target PV Present Value Current Savings PMT Payment per period payment_per_period / Monthly Investment needed RATE Rate of return rate NPER Number of periods target_date

Out of the 5 variables, if you know any 4, the 5th can be calculated by solving the equation. You can refer the blog post for more details.

"},{"location":"reference/tax/","title":"Tax","text":"

Paisa provides few features to help with tax filing and tax optimization.

"},{"location":"reference/tax/#disclaimer","title":"Disclaimer","text":"

The author of this tool is not an accountant, the calculations are made based on their interpretation of rules and regulation. This tool is distributed free hoping it would be useful. The users are advised to consult a tax accountant before making any decision based on the information provided here. Check the LICENSE of paisa for more details.

"},{"location":"reference/tax/capital-gains/","title":"Capital Gains","text":"

Mutual Funds are considered as capital asset and capital gains tax will be charged on any gains. Capital Gains page shows the financial year wise capital gains tax based on the withdrawal transaction. The sum total, account wise breakdown, and per buy/sell match information are available.

Only commodities with tax_category are considered. Please check Tax Harvesting page for configuration details.

"},{"location":"reference/tax/capital-gains/#gain","title":"Gain","text":"

The difference between the purchase and sell price.

"},{"location":"reference/tax/capital-gains/#taxable-gain","title":"Taxable Gain","text":"

The gain after applying Indexation or Grandfathering provision.

Based on the duration between the purchase and sell date, an asset might be classified as Short Term or Long Term.

"},{"location":"reference/tax/capital-gains/#short-term-tax","title":"Short Term Tax","text":"

This would be a percentage of the Taxable Gain. The percentage varies based on the asset class.

"},{"location":"reference/tax/capital-gains/#long-term-tax","title":"Long Term Tax","text":"

This would be a percentage of the Taxable Gain. The percentage varies based on the asset class.

"},{"location":"reference/tax/capital-gains/#taxable-at-slab-rate","title":"Taxable at Slab Rate","text":"

There are cases where the gain would be added to taxable income and charged Slab rate. Since the tax rate would depend on the person, the whole taxable amount is shown instead of the tax. You can multiply this with your slab rate to get the tax amount.

"},{"location":"reference/tax/schedule-al/","title":"Schedule AL","text":"

As per the Indian Income tax law, citizens are obligated to report their entire Assets and Liabilities if the total income exceeds \u20b950 lakh. Paisa helps with the computation of the amount.

code Section Details immovable A (1) Immovable Assets metal B (1) (i) Jewellery, bullion etc. art B (1) (ii) Archaeological collections, drawings, painting, sculpture or any work of art vehicle B (1) (iii) Vehicles, yachts, boats and aircrafts bank B (1) (iv) (a) Financial assets: Bank (including all deposits) share B (1) (iv) (b) Financial assets: Shares and securities insurance B (1) (iv) (c) Financial assets: Insurance policies loan B (1) (iv) (d) Financial assets: Loans and advances given cash B (1) (iv) (e) Financial assets: Cash in hand liability C (1) Liabilities

All you need to do is to specify the accounts that belong to each section. Paisa will compute the total as on the last day of the previous financial year.

schedule_al:\n    - code: bank\n      accounts:\n          - Assets:Checking\n    - code: share\n      accounts:\n          - Assets:Equity:*\n          - Assets:Debt:*\n
"},{"location":"reference/tax/tax-harvesting/","title":"Tax Harvesting","text":"

Gains from asset types like Mutual Fund, Stock are subject to capital gains tax. The taxation rate itself differs based on how long you hold your investment, whether it's debt or equity, whether you have more than 1 Lakh gains in a year etc. To further complicate things, there might be exit load applicable.

Paisa takes a generic approach and let the user configure when a commodity is safe to harvest. There are two fields related to tax harvesting.

  1. harvest - specifies the number of days after which the commodity is eligible for tax harvesting. This should be set based on fund exit load, fund category etc

  2. tax_category - This defines how the taxes are calculated as the government usually tweaks the tax code regularly with various rules like grandfathering, cost inflation index adjustment, etc.

    1. equity65 - This is for 65% or more investment in Indian equity.

    2. equity35 - This if for 35% or more investment in India equity but less than 65%

    3. debt - This is for debt funds.

    4. unlisted_equity - This is for unlisted foreign on Indian equity.

commodities:\n  - name: NIFTY\n    type: mutualfund\n    code: 120716\n    harvest: 365\n    tax_category: equity65\n  - name: ABSTF\n    type: mutualfund\n    code: 119533\n    harvest: 1095\n    tax_category: debt\n

The tax harvest page will show the list of accounts eligible for harvesting.

"},{"location":"reference/tax/tax-harvesting/#multiple-folios","title":"Multiple Folios","text":"

Paisa uses FIFO method within an Account. If you have multiple folios, this might result in incorrect values. The issue can be solved by using a different Account for each folio.

"},{"location":"blog/archive/2024/","title":"2024","text":""},{"location":"blog/category/configuration/","title":"configuration","text":""},{"location":"blog/category/locale/","title":"locale","text":""}]} \ No newline at end of file