A dashboard can tell me what the current month looks like and still leave the harder question unanswered: is the portfolio actually moving in a better direction?
That question sounds like a request for one chart. It is really a request for consistent history. Revenue, costs, pauses, yearly renewals, allocations, currencies, and imported data all need to mean the same thing in every month before drawing a line between them is useful.
Disclosure: I make MarginDeck. This article describes my own work on the product.
MarginDeck 1.4, released on September 2, 2026, adds Portfolio Performance Trend. It compares recorded revenue, scheduled costs, and estimated contribution profit over 6 or 12 months. The release also lays the local history and currency groundwork needed for that comparison.
The chart compares saved records and scheduled costs over time.
Why I replaced two charts with one comparison
The earlier Dashboard separated scheduled-cost and recorded-revenue trends. Each chart worked, but reading the relationship required remembering one shape while looking at another.
Version 1.4 puts three series on the same monthly calendar:
| Series | What it represents |
|---|---|
| Recorded revenue | Revenue saved for that month, whether entered manually or accepted from a sync |
| Scheduled cost | Expected costs resolved from the billing terms and activity active in that month |
| Estimated contribution profit | Recorded revenue minus scheduled cost for the same month |
The chart offers 6- and 12-month ranges. Pointing to a month, focusing the chart, or moving with the keyboard exposes the exact values in a fixed detail area. The lines help reveal direction; the values remain available when precision matters.
Combining the series also prevents an easy visual mistake. Rising revenue can look encouraging until costs are placed beside it. A cost spike can look alarming until the yearly renewal behind it is visible. The useful question is not whether one line went up. It is what changed across the three related measures.
One calendar, three series, one set of rules
I did not want the chart to introduce a second, simplified accounting model merely to produce smoother lines.
The monthly points use the same rules as the rest of MarginDeck:
- monthly costs appear in each applicable month;
- yearly costs stay in their recorded billing month;
- one-time costs stay in the month in which they are recorded;
- price and schedule stages use the terms effective for each expected charge;
- Pause and Resume history determines whether a scheduled occurrence exists;
- allocation history uses the split effective in that month;
- a recorded zero-revenue month remains zero; missing provider history is not filled in;
- a cost-only month can show negative estimated contribution profit.
This creates sharper movements than an amortized or smoothed chart. That is deliberate. A $120 annual renewal and a $10 monthly subscription may average to the same amount, but they do not create the same cash-timing or cancellation decision.
The trend is a historical comparison of recorded inputs and scheduled estimates. It is not a revenue forecast, MRR model, ARR calculation, or promise about future performance.
Synced history starts when the app actually saves it
Manual revenue already has a month attached to each record. Provider syncs needed a clearer historical boundary.
Starting with MarginDeck 1.4, each successful RevenueCat or Stripe sync can save monthly aggregate net revenue locally. A source identity includes the provider context, external item, currency, and metric. Syncing the same logical month again replaces the saved aggregate instead of adding a duplicate amount.
This release does not backfill the previous 12 months. The first useful trend may therefore contain more manual history than provider history. I chose to show that boundary instead of implying the app had collected data it never received.
Monthly provider history grows from successful 1.4 syncs onward. A new connection cannot instantly produce a year of history.
Unassigned revenue stays visible without entering the portfolio total
A synced item can be linked to an existing Product, used to create a Product, or kept unassigned for later review.
Unassigned amounts remain available in Revenue, but they do not enter Dashboard totals or the Portfolio Performance Trend. Otherwise a number with no product relationship could quietly change a portfolio comparison before the user reviews it.
Changing the Product mapping updates the saved months for that source identity. The amount history belongs to the source; the mapping explains where that history belongs in the portfolio.
That separation is useful beyond MarginDeck: preserve the imported fact, preserve its identity, and make classification an explicit decision.
Currency conversion needs a time policy
A portfolio with USD hosting, a EUR service, and CNY revenue cannot be added meaningfully by removing the currency codes.
MarginDeck 1.4 can estimate supported currencies—USD, EUR, GBP, CNY, and JPY—in one display currency using cached European Central Bank reference rates. Original amounts remain visible, and the rate policy changes with the kind of month being viewed:
| Period | Reference-rate treatment |
|---|---|
| Closed historical month | Average of the available daily observations for that month |
| Current month | Provisional average of observations available so far |
| Future scheduled value | Latest cached daily observation |
These are informational estimates. They are not live market quotes, card-network rates, settlement rates, or the exchange rate attached to an actual transaction.
If a required rate is missing, the safer result is an explicit error rather than a fabricated total. A conversion policy should make uncertainty visible, not use a precise-looking number to hide it.
Local history changes the backup boundary
Provider tokens and restricted keys still belong in the macOS Keychain. They are not written into MarginDeck's business database or exported backup.
The monthly aggregates are different. Once the user reviews and saves them, they become local business records. Backup format v5 can therefore include monthly source identity, currency, aggregate amount, mapping, sync time, and cached reference rates while continuing to exclude connection credentials and StoreKit state.
The credential grants access; the aggregate is a record the user chose to keep. They should not share the same storage policy.
A practical way to read the new trend
My own review sequence is intentionally small:
- Choose the display currency used for portfolio comparison.
- Enter or sync the current month's known revenue.
- Resolve any unassigned synced items before treating the Dashboard total as complete.
- Compare 6 months first, then use 12 months when yearly renewals or seasonal changes need context.
- Inspect the exact month behind a peak or drop.
- Check the underlying revenue records, billing terms, pauses, and allocation history before drawing a conclusion.
The chart should point to a question worth investigating. It should not answer a product decision on its own.
Disclosure: I am Junhua Jin, the developer of MarginDeck and the author of SwingCodeLab. You can download MarginDeck from the Mac App Store.