Guide

Use trading accounts

Turn on the Use Trading Accounts book option so every transaction that mixes currencies balances in each currency, and see the Trading accounts it creates.

A transaction in two currencies balances in value, but each currency taken alone does not: you gave up 108.50 dollars and received 100.00 euros. Trading accounts fix that. With the option on, red-ale adds balancing splits to a hidden tree of TRADING accounts (Trading:CURRENCY:USD, Trading:CURRENCY:EUR), so that the splits in each currency sum to zero on their own. The Trading account for each currency then shows how much of it you have bought or sold, which is what accountants use to find a currency gain or loss.

It is a book option, so it is stored in the book and GnuCash honours it when it opens the file.

Steps

  1. Turn it on with book.setOptions and useTradingAccounts: true. No existing transaction changes; only transactions you post or edit afterwards get trading splits. book.options shows the current setting.
  2. Post as usual with transaction.post. Give the transaction's currency, and an amount on each split whose account is in another commodity (see Multiple currencies). red-ale adds the trading splits itself.
  3. Look at the result. The transaction has two more splits than you sent. account.list now includes the Trading accounts, which are placeholders: do not post to them yourself.

Turning the option off stops new trading splits from being added, but keeps the ones already there.

Example

Example: with a new, empty book open as book.gnucash, at 2024-07-15T12:00:00Z.

JSON-RPC

Request:

{"jsonrpc":"2.0","id":1,"method":"book.setOptions","params":{"useTradingAccounts":true}}

Response:

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "useTradingAccounts": true,
    "…": "…"
  }
}

Request:

{"jsonrpc":"2.0","id":2,"method":"account.create","params":{"name":"Checking","type":"BANK","commodity":"USD"}}

Response:

{
  "jsonrpc": "2.0",
  "id": 2,
  "result": "…"
}

Request:

{"jsonrpc":"2.0","id":3,"method":"account.create","params":{"name":"Euro Bank","type":"BANK","commodity":"EUR"}}

Response:

{
  "jsonrpc": "2.0",
  "id": 3,
  "result": "…"
}

Request:

{"jsonrpc":"2.0","id":4,"method":"transaction.post","params":{"datePosted":"2024-07-02","description":"Buy euros","currency":"USD","splits":[{"account":"Euro Bank","value":"108.50","amount":"100.00"},{"account":"Checking","value":"-108.50"}]}}

Response:

{
  "jsonrpc": "2.0",
  "id": 4,
  "result": {
    "balanced": true,
    "splits": [
      {
        "accountName": "Euro Bank",
        "…": "…"
      },
      {
        "accountName": "Trading:CURRENCY:USD",
        "…": "…"
      },
      {
        "accountName": "Checking",
        "…": "…"
      },
      {
        "accountName": "Trading:CURRENCY:EUR",
        "value": {
          "num": "-10850",
          "denom": "100"
        },
        "amount": {
          "num": "-10000",
          "denom": "100"
        },
        "…": "…"
      }
    ],
    "…": "…"
  }
}

Command line

red-ale exec --book book.gnucash --script - <<'EOF'
book.setOptions {"useTradingAccounts":true}
account.create {"name":"Checking","type":"BANK","commodity":"USD"}
account.create {"name":"Euro Bank","type":"BANK","commodity":"EUR"}
transaction.post {"datePosted":"2024-07-02","description":"Buy euros","currency":"USD","splits":[{"account":"Euro Bank","value":"108.50","amount":"100.00"},{"account":"Checking","value":"-108.50"}]}
EOF

It prints:

[
  {
    "useTradingAccounts": true,
    "…": "…"
  },
  "…",
  "…",
  {
    "balanced": true,
    "splits": [
      {
        "accountName": "Euro Bank",
        "…": "…"
      },
      {
        "accountName": "Trading:CURRENCY:USD",
        "…": "…"
      },
      {
        "accountName": "Checking",
        "…": "…"
      },
      {
        "accountName": "Trading:CURRENCY:EUR",
        "value": {
          "num": "-10850",
          "denom": "100"
        },
        "amount": {
          "num": "-10000",
          "denom": "100"
        },
        "…": "…"
      }
    ],
    "…": "…"
  }
]

MCP tool call

Tool call:

{"name":"book.setOptions","arguments":{"useTradingAccounts":true}}

Result:

{
  "structuredContent": {
    "useTradingAccounts": true,
    "…": "…"
  }
}

Tool call:

{"name":"account.create","arguments":{"name":"Checking","type":"BANK","commodity":"USD"}}

Result:

{
  "content": [
    {
      "type": "text",
      "text": "\"…\""
    }
  ]
}

Tool call:

{"name":"account.create","arguments":{"name":"Euro Bank","type":"BANK","commodity":"EUR"}}

Result:

{
  "content": [
    {
      "type": "text",
      "text": "\"…\""
    }
  ]
}

Tool call:

{"name":"transaction.post","arguments":{"datePosted":"2024-07-02","description":"Buy euros","currency":"USD","splits":[{"account":"Euro Bank","value":"108.50","amount":"100.00"},{"account":"Checking","value":"-108.50"}]}}

Result:

{
  "structuredContent": {
    "balanced": true,
    "splits": [
      {
        "accountName": "Euro Bank",
        "…": "…"
      },
      {
        "accountName": "Trading:CURRENCY:USD",
        "…": "…"
      },
      {
        "accountName": "Checking",
        "…": "…"
      },
      {
        "accountName": "Trading:CURRENCY:EUR",
        "value": {
          "num": "-10850",
          "denom": "100"
        },
        "amount": {
          "num": "-10000",
          "denom": "100"
        },
        "…": "…"
      }
    ],
    "…": "…"
  }
}