Documentation

OpenFolio Documentation

Complete reference for every feature, formula, and import format. Use the contents below to jump to any section.

Getting Started

From zero to a working portfolio in minutes

What is OpenFolio?

OpenFolio is an Australian investment portfolio tracker that consolidates stocks, ETFs, crypto, superannuation, dividends, and equity grants into one dashboard. It runs Australian CGT calculations (FIFO/LIFO/MIN_GAINS), tracks franking credits, and projects dividend income — all with your real data.

First steps

1

Add your first trade

Go to Trades → + Add trade. Enter ticker, market, quantity, price, and date. Or import from your broker CSV.

2

Import history

Use Trades → Import CSV to bulk-import from MooMoo, CommSec, Stake, Webull, and more.

3

Record dividends

Go to Dividends → Import CSV and upload your dividend spreadsheet, or record manually.

4

Set up net worth

Add bank accounts, super balances, and any property under Net Worth.

5

Review tax

Go to Tax to see realised gains, the 50% CGT discount analysis, and your FY estimate.

Data flow

Trades (BUY/SELL) → holdings-engine → Holdings + Tax Lots

Holdings + Live Prices → bi-engine → Dashboard metrics

Tax Lots + Strategy → tax-engine → CGT summary

Dividends → dividend-engine → Franking credits + Forecast

Net Worth

Your complete financial position in one number

How it's calculated

Net WorthPortfolio Value + Crypto + Super + Bank + Property − Debt
Portfolio ValueΣ(current_price × quantity) for all holdings
Crypto ValueΣ(coingecko_price × quantity) for all crypto
DebtΣ(credit_card_balance) + other liabilities

Categories

Portfolio

Stock & ETF holdings at current market price

Crypto

Crypto positions valued via CoinGecko live prices

Super

Latest super balance snapshot per fund

Property & Assets

Real estate, vehicles, collectibles — manual entry

Cash & Banking

Bank account balances imported from statement CSVs

Credit Cards

Outstanding balances tracked as liabilities

Portfolio value uses live prices where available. If a price feed is unavailable for a ticker, cost basis is used as a fallback — the holding is still included but may understate market value.

Portfolio & Trades

Cost basis, market value, and unrealised P&L

Cost basis

Every BUY trade creates a tax lot. The cost basis for a holding is the sum of all lot costs for units still held. Brokerage is included in cost basis (it raises your acquisition cost, reducing your eventual taxable gain).

Price in AUDprice_aud = price_foreign / aud_rate
Cost per unit(price_aud × qty + brokerage) / qty
Total cost basisΣ(quantity × cost_per_unit) over all open lots
Unrealised P&L(current_price × quantity) − cost_basis
Unrealised P&L %(P&L / cost_basis) × 100
Market valuecurrent_price × total_quantity

AUD rate for foreign trades

For US stocks, set the AUD/USD rate at time of trade. The field labelled "AUD rate" is units of foreign currency per 1 AUD. Example: if 1 AUD = 0.64 USD, enter 0.64. A $100 USD price becomes $156.25 AUD at that rate.

Portfolio cost-over-time chart

The green stepped line on the Portfolio page shows cumulative cost basis over time — it steps up on each BUY and down on each SELL (by the lot cost, not sale price). The blue line (where available) shows current market value at today's date, giving a visual P&L gap.

Lot Accounting

FIFO, LIFO, and MIN_GAINS — how each BUY and SELL is matched

What is a tax lot?

Every BUY trade creates one lot: a record of quantity, cost_per_unit_aud, and acquisition_date. When you SELL, lots are consumed in a strategy-defined order to calculate your realised gain.

Disposal strategies

FIFOFirst In, First Out

Oldest lots consumed first. ATO default — lowest audit risk. Maximises CGT discount eligibility when shares have been held long.

LIFOLast In, First Out

Newest lots consumed first. Useful when recent purchases had a higher cost — reduces gross gain on short-term sells.

MIN_GAINSMinimum Gains

Lots sorted by highest cost_per_unit descending — minimises your realised capital gain on any given sell.

Worked example

Suppose you bought VAS in two tranches, then sold 80 units:

BUY 100 units @ $90.00 AUD on 2023-01-10 → Lot A: cost/unit = $90.00 BUY 50 units @ $95.00 AUD on 2024-03-15 → Lot B: cost/unit = $95.00 SELL 80 units @ $105.00 AUD on 2025-06-01

FIFO

Consume Lot A first (80 of 100 units)
Cost basis: 80 × $90 = $7,200
Proceeds: 80 × $105 = $8,400
Gain: $1,200 (held 878 days → 50% discount ✓)

LIFO

Consume Lot B first (50 units), then 30 from Lot A
Cost basis: 50×$95 + 30×$90 = $7,450
Proceeds: $8,400
Gain: $950 (Lot B: 442 days → no discount)

MIN_GAINS

Highest cost first → Lot B ($95), then Lot A
Same as LIFO here
Gain: $950 (minimised)

The ATO currently mandates FIFO for most individual taxpayers using standard CGT event rules. LIFO and MIN_GAINS are provided for modelling purposes. Consult your tax adviser on which method applies to your situation.

Australian CGT Engine

Capital Gains Tax: 50% discount, loss offsets, FY estimates

CGT event

A CGT event occurs when you dispose of a CGT asset — selling shares, ETFs, or crypto. The gain (or loss) is the difference between your sale proceeds and the asset's cost base.

Formulas

Gross gain (per lot)(sell_price − sell_brok/unit) × qty − cost/unit × qty
50% discount eligibleheld_days >= 365
Discountable gaingross_gain × 0.5 (if eligible)
Net taxable (FY)non_disc_gains + disc_gains × 0.5 − losses
Tax estimatenet_taxable × 0.39 (39% marginal proxy)

How losses work

Capital losses offset capital gains in the same FY. If losses exceed gains, the surplus carries forward to future years (not shown in the current estimate — enter carried-forward losses manually). The 50% discount applies only to gains, not losses — you cannot discount a loss.

Australian financial year

The ATO FY runs 1 July → 30 June. FY2025 = 1 Jul 2024 → 30 Jun 2025. The Tax page groups all realised events by the FY in which the SELL date falls.

The 39% tax rate is a proxy for a high-income marginal rate. Actual tax depends on your total income, offsets, and Medicare levy. This is an estimate only — not tax advice.

Dividends & Franking Credits

Cash income, ATO gross-up, and projected yield

Franking credit formula

Australian companies pay tax at 30% before distributing dividends. If a dividend is "fully franked", the ATO allows you to claim a credit for the tax already paid — the 30/70 gross-up:

Franking creditcash × (franking_pct / 100) × (30 / 70)
Gross incomecash_dividend + franking_credit
Effective gross-up (100% franked)cash × (30/70) ≈ cash × 0.4286
Yield on costprojected_annual / cost_basis × 100
Projected annualtrailing_12m_cash × (365 / days_in_window)

Example

CBA pays $2.50 per share, 100% franked, you hold 200 shares: Cash received: 200 × $2.50 = $500.00 Franking credit: $500 × (30/70) = $214.29 Gross income: $714.29 (The $214.29 is a tax offset on your return)

Partial franking

ETF distributions often carry partial franking (e.g. 30% or 60%) because the underlying portfolio is a mix of fully-franked, unfranked, and foreign income. The import page lets you set a default; you can edit individual records afterwards.

DRP (Dividend Reinvestment Plan)

Mark a dividend as DRP to flag it as reinvested. DRP dividends still count as assessable income in the year received — you should also add a matching BUY trade at the DRP issue price.

Crypto Holdings

Snapshot-based positions with live CoinGecko prices

How it works

Crypto holdings are stored as snapshots: symbol, platform, quantity, and average cost in AUD. Live prices are fetched from CoinGecko on each page load. P&L is calculated against your average cost.

Crypto valuecoingecko_price_aud × quantity
Unrealised P&Lvalue − (avg_cost_aud × quantity)
P&L %(P&L / (avg_cost × qty)) × 100

Lot-level CGT tracking for crypto (tracking each individual BUY/SELL event) is on the roadmap. Currently, crypto P&L is based on average cost only — not suitable for ATO reporting of realised gains.

Supported imports

Coinstash and Bybit CSV exports are supported. Binance support is planned.

Superannuation

Balance snapshots and contribution tracking

Balance tracking

Super balances are recorded as point-in-time snapshots — date and balance per fund. The chart on the Super page plots these snapshots with selectable periods (3M / 1Y / 3Y / All). Add a new snapshot each time you check your fund statement.

Contributions

Each contribution can be categorised as:

  • Employer SGC11.5% (FY2025) of ordinary time earnings, mandatory
  • Voluntary concessionalPre-tax contributions — count toward $30k/yr cap
  • Salary sacrificePre-tax, reduces assessable income
  • Non-concessionalAfter-tax personal contributions
  • Government co-contributionLow-income earners: up to $500 government match
  • FHSSFirst Home Super Saver Scheme withdrawals

SMSF support and retirement projection modelling are on the roadmap.

Equity & ESS

RSUs, options, performance rights, and employee share schemes

Grant types

RSU

Restricted Stock Unit — shares granted subject to vesting. Taxed as income when vested at FMV.

Option

Right to buy shares at strike price. Gain = (FMV − strike) × qty at exercise.

Performance Right

RSU variant — vesting contingent on performance milestones.

ESS Discount

Employee Share Scheme — shares bought below market price. Discount is assessable income.

Restricted Share

Shares issued upfront but legally restricted until vest date.

Vest lifecycle

SCHEDULED → grant awarded, vesting in future

VESTED → vest date passed, shares released

EXERCISED → options exercised (options only)

SOLD → vested shares subsequently sold

LAPSED → unvested grant cancelled (left company etc.)

Net vest value

RSU net valuevest_quantity × current_market_price
Option intrinsic value(current_price − strike_price) × qty (if > 0)
ESS discount (income)market_price_at_grant − grant_price

GEMS import

Export your grant summary from GEMS as CSV. Expected columns:

Grant ID,Grant Date,Grant Type,Ticker,Employer,Total Granted,Strike Price,Scheme Type,Vest Date,Vest Quantity,Status

Importing Data

Supported brokers, bank formats, and step-by-step export guides

CommSec (CDIA Cash Account)

CommSec exports a cash account transaction log. Trades appear as rows with Reference starting 'C'. Bank transfers (Reference 'R') are ignored automatically.

Date,Reference,Details,Debit($),Credit($),Balance($) 26/03/2026,C173327579,B 7 VGS @ 142.980000 ,1005.85,,1005.85 23/02/2026,C171978921,B 1666 ZIP @ 1.815000 ,3043.74,,3043.74
  • Log in → My Portfolio → click your CDIA Cash Account
  • Go to Transactions tab → set date range → Download CSV
  • Brokerage is auto-calculated: |total_debit − qty × price|
  • All trades assumed ASX, AUD

MooMoo

MooMoo exports an Excel file from the FY Summary page. Supports both AUS (ASX) and US trades on separate sheets.

Market,Transaction Date,Security Type,Direction,Security Code,Quantity,Currency,Avg Price,Transaction Amount,Transaction Fee ASX,31/07/2024,,Buy,NDQ,12,AUD,42.99,-515.88,3.00
  • Account → Statements → FY Summary → download .xlsx
  • Both sheets (AUS + Wall St) are processed automatically
  • Positions CSV also supported — creates synthetic BUY at avg cost
  • US trades in USD — set AUD rate on import

Stake

Stake exports an Excel file from the Tax & reporting section.

Trade Date,Settlement Date,Symbol,Name,Side,Units,Avg. Price,Value,Fees 2025-07-24,2025-07-25,TSLA,Tesla Inc,Buy,10,305.84,3058.40,3.00
  • Account → Tax & reporting → Financial year reports
  • Download the Investment Activity .xlsx
  • US trades in USD — set AUD rate on import

Webull

Webull exports a CSV from Orders → Trade History. Supports stocks, ETFs, and options.

Symbol,Name,Currency,Type,Trade Date,Time,Buy/Sell,Quantity,Trade Price,Gross Amount,Net Amount,Comm/Fee/Tax TQQQ,ProShares UltraPro QQQ,USD,OPTION,2025/04/16,14:02:14,SELL,1,0.35,35.00,34.42,-0.58
  • Orders → Trade History → Export → download CSV
  • OPTION type auto-detected — price stored per-contract
  • All trades in USD — set AUD rate

Pepperstone (cTrader)

Pepperstone XLSX has one row per closed position. Each row becomes a BUY + SELL pair at the opening/closing prices.

Symbol,Opening direction,Closing time,Entry price,Closing price,Closing Quantity,Net AUD AUDUSD,Buy,16/05/2022 13:39:14,0.69277,0.69377,0.01,1.36
  • cTrader → History tab → Closed Positions → Export to Excel
  • Each row emits 2 trades: BUY at entry, SELL at close
  • Net AUD stored in notes on the SELL leg

Coinstash

Coinstash exports a transaction CSV from Profile → Transaction History.

TransactionId,UserId,AccountId,AccountType,TransactedOn,Category,Type,OrderId,OrderType,Symbol,Amount,AmountType uuid,uuid,uuid,Trading,04-03-2026 07:41:13,Trade,Debit,order-uuid,Buy,AUD,823.24,Fiat
  • Profile (top right) → Transaction History → Export
  • Buy/Sell trades auto-detected; rewards and fees filtered
  • All prices in AUD

Dividend Spreadsheet

Your personal dividend record in the standard format. Rows with nil dividend ('$ -') are skipped. Market and franking % are set at import time.

Ex-Dividend Date,Pay Date,Share,No Shares,Dividend,FY,Total FY 01/04/2020,24/04/2020,VAS,11,$ 4.40,2020, 01/04/2020,24/04/2020,VGS,11,$ 3.00,2020, 01/07/2020,16/07/2020,VDHG,50,$ 33.99,2020,
  • Dividends → Import CSV → upload CSV or .xlsx directly
  • Set market (default ASX) and default franking % before importing
  • Ex-date is stored in the notes field for each dividend record
  • Edit individual records to set per-dividend franking % from your tax statement

Bank Statements (CBA / NAB / ANZ / Westpac)

Download your bank transaction CSV from internet banking. Used for Cash & Banking net worth tracking.

Date,Amount,Description,Balance 01/05/2026,-45.00,Woolworths Metro,1234.56 28/04/2026,2500.00,Salary,1279.56
  • Each bank has minor date/column format differences — all handled automatically
  • Imported transactions appear in the Cash & Banking section of Net Worth
  • Not used for trade tracking — use the broker-specific importers for that

Generic CSV

Any broker not listed above — use this flexible format. Column names are case-insensitive.

ticker,type,quantity,price,currency,date,brokerage CBA,Buy,100,98.50,AUD,2024-03-15,9.90 AAPL,Buy,10,175.50,USD,2024-03-15,0
  • Date formats: YYYY-MM-DD and DD/MM/YYYY both accepted
  • Type: Buy/Sell, B/S, Purchase/Sale all accepted
  • Currency: AUD or USD (set conversion rate after upload)

CSV Templates

Copy and fill — or download from the Import page for each broker

Generic Trade CSV

ticker,type,quantity,price,currency,date,brokerage CBA,Buy,100,98.50,AUD,2024-03-15,9.90 VAS,Buy,200,95.00,AUD,2024-04-01,9.90 AAPL,Sell,10,175.50,USD,2024-06-15,0

Dividend Spreadsheet

Ex-Dividend Date,Pay Date,Share,No Shares,Dividend,FY,Total FY 01/04/2024,24/04/2024,VAS,200,$ 167.89,2024, 01/04/2024,24/04/2024,VGS,64,$ 64.19,2024, 01/07/2024,16/07/2024,NDQ,187,$ 171.45,2024,

GEMS Grant Summary

Grant ID,Grant Date,Grant Type,Ticker,Employer,Total Granted,Strike Price,Scheme Type,Vest Date,Vest Quantity,Status G001,01/01/2022,RSU,CBA,Commonwealth Bank,1000,,ESOP,01/01/2024,250,Vested G001,01/01/2022,RSU,CBA,Commonwealth Bank,1000,,ESOP,01/01/2025,250,Scheduled

Bank — CommBank

Date,Amount,Description,Balance 01/05/2026,-45.00,Woolworths Metro,3456.78 30/04/2026,2500.00,Salary credit,3501.78

Bank — NAB

Date,Amount,Description,Balance 01-May-26,-45.00,Woolworths Metro,3456.78 30-Apr-26,2500.00,Salary credit,3501.78

Bank — ANZ

Date,Description,Amount,Balance 01/05/2026,Woolworths Metro,-45.00,3456.78 30/04/2026,Salary credit,2500.00,3501.78

Bank — Westpac

Date,Description,Debit,Credit,Balance 01/05/2026,Woolworths Metro,45.00,,3456.78 30/04/2026,Salary credit,,2500.00,3501.78

Formula Reference

Every calculation used in the app, in one place

All amounts in AUD unless stated

Foreign price → AUDprice_aud = price_foreign / aud_rate
Cost per unit (BUY)(price_aud × qty + brokerage) / qty
Total cost basisΣ(qty × cost_per_unit) over open lots
Market valuecurrent_price × total_quantity
Unrealised P&Lmarket_value − cost_basis
Unrealised P&L %(P&L / cost_basis) × 100
Realised gain (lot)(sell_price − sell_brok/unit) × qty − cost/unit × qty
CGT discount eligibleheld_days >= 365 → gain × 0.5
Net taxable gain (FY)non_disc + disc × 0.5 − losses
CGT tax estimatenet_taxable × 0.39
Franking creditcash × (franking_pct / 100) × (30 / 70)
Gross dividendcash + franking_credit
Projected annual yieldtrailing_12m / cost_basis × 100
CommSec brokerage|total_debit − qty × price|
Net worthportfolio + crypto + super + bank + property − debt
Option intrinsic valuemax(0, current_price − strike) × qty
ESS discount (income)market_price_at_grant − grant_price