ray-finance 0.3.0 → 0.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,5 +1,5 @@
1
1
  <p align="center">
2
- <img src=".github/ray-logo.png" alt="Ray" width="120" />
2
+ <img src=".github/ray-logo.png" alt="Ray" width="108" />
3
3
  </p>
4
4
 
5
5
  <p align="center">
@@ -14,40 +14,17 @@
14
14
 
15
15
  <br />
16
16
 
17
- ```
18
- Friday, Mar 28
19
-
20
- net worth $45,230 +$120
21
-
22
- spending $2,340 this month · $340 less vs last month
23
- Dining -$114 · Shopping -$142 · Groceries -$73
24
-
25
- ▓▓▓▓▓▓▓░ Dining 92%
26
-
27
- ▓▓▓▓░░░░ Emergency fund $18,200/$40,000
28
-
29
- upcoming Netflix $16 in 3d · Comcast $142 in 6d
30
-
31
- score 72/100 · 5d no dining · 3d on pace
32
-
33
- ──────────────────────────────────────────────────
34
-
35
- ❯ if I quit my job to freelance, how long can I survive?
36
-
37
- Based on your last 3 months: you burn $4,820/mo after
38
- fixed costs. With $18,200 in savings, that's
39
- 3.8 months of runway at current spend.
40
-
41
- Cut dining and shopping to last-month levels and
42
- you stretch to 5.1 months. Land one $8k contract
43
- in that window and you never dip below $10k.
44
- ```
17
+ <p align="center">
18
+ <img src=".github/ray-demo.png" alt="Ray demo" />
19
+ </p>
45
20
 
46
21
  Open Ray and it shows your net worth, spending vs last month, budget pacing, and upcoming bills — before you type a word. Ask a question and it answers from your real data, not guesses. Local-first. Encrypted. Open source.
47
22
 
48
23
  ## Features
49
24
 
50
25
  - **It already knows** — Every conversation starts with a real-time financial briefing. Net worth, spending velocity, budget alerts, goal pace, upcoming bills, and your daily score. No "let me look that up."
26
+ - **Persistent context** — Ray maintains a financial profile that evolves with you: income, goals, strategy, key decisions, and open items. It updates this context as your situation changes, so every conversation picks up where the last one left off.
27
+ - **Long-term memory** — Important details from conversations are saved as memories. Mention you're saving for a house or switching jobs and Ray remembers — without you repeating yourself.
51
28
  - **Bank sync via Plaid** — Connect checking, savings, credit cards, investments, and loans
52
29
  - **Encrypted local database** — All data stays on your machine in an AES-256 encrypted SQLite database
53
30
  - **Daily scoring** — A 0-100 behavior score with streaks and 14 unlockable achievements. No restaurants for a week? That's Kitchen Hero. Five zero-spend days? Monk Mode.
@@ -65,6 +42,26 @@ Open Ray and it shows your net worth, spending vs last month, budget pacing, and
65
42
  npm install -g ray-finance
66
43
  ```
67
44
 
45
+ ## Try It
46
+
47
+ Explore Ray with realistic fake data — no bank accounts needed.
48
+
49
+ ```bash
50
+ ray demo # seed a demo database
51
+ ray --demo status # financial overview
52
+ ray --demo accounts # linked accounts with balances
53
+ ray --demo spending # spending breakdown by category
54
+ ray --demo budgets # budget tracking
55
+ ray --demo goals # financial goal progress
56
+ ray --demo score # daily score, streaks, achievements
57
+ ray --demo alerts # financial alerts
58
+ ray --demo transactions # recent transactions
59
+ ```
60
+
61
+ The dashboard commands work with no setup at all. To also try the AI chat with demo data, run `ray setup` first and add an [Anthropic API key](https://console.anthropic.com) or Ray API key — then `ray --demo` will start an interactive session where you can ask questions about the fake portfolio.
62
+
63
+ When you're ready to connect real accounts, run `ray link`.
64
+
68
65
  ## Quick Start
69
66
 
70
67
  ```bash
@@ -98,6 +95,8 @@ Run `ray --help` to see all available commands.
98
95
  | Command | Description |
99
96
  |---------|-------------|
100
97
  | `ray` | Interactive AI chat with your financial advisor |
98
+ | `ray demo` | Seed a demo database with realistic fake data |
99
+ | `ray --demo <cmd>` | Run any command against demo data |
101
100
  | `ray setup` | Configure API keys and preferences |
102
101
  | `ray link` | Connect a new bank account |
103
102
  | `ray sync` | Pull latest transactions and balances |
@@ -155,6 +154,7 @@ Ray stores everything in `~/.ray/`:
155
154
  context.md # Persistent financial context for AI
156
155
  data/
157
156
  finance.db # Encrypted SQLite database
157
+ demo.db # Demo database (created by `ray demo`)
158
158
  sync.log # Daily sync output
159
159
  ```
160
160
 
@@ -174,6 +174,7 @@ RAY_API_KEY= # Ray API key (managed mode, replaces the above)
174
174
 
175
175
  ## Roadmap
176
176
 
177
+ - [ ] Bring your own model — use any LLM provider (OpenAI, Ollama, open-source models, etc.)
177
178
  - [ ] Daily digest email — morning summary of your finances
178
179
 
179
180
  Have an idea? [Open a PR](https://github.com/cdinnison/ray-finance/pulls).
@@ -11,4 +11,6 @@ export declare function showSpending(period?: string): Promise<void>;
11
11
  export declare function showBudgets(): void;
12
12
  export declare function showGoals(): void;
13
13
  export declare function showScore(): void;
14
+ export declare function runAdd(): Promise<void>;
15
+ export declare function runRemove(): Promise<void>;
14
16
  export declare function showAlerts(): void;
@@ -5,6 +5,7 @@ import { getLatestScore, getAchievements, getMonthlySavings } from "../scoring/i
5
5
  import { generateAlerts } from "../alerts/index.js";
6
6
  import { runDailySync } from "../daily-sync.js";
7
7
  import { startLinkServer } from "../server.js";
8
+ import { addManualAccount, getManualAccounts, removeManualAccount, scrapeRedfinEstimate } from "../property.js";
8
9
  import { heading, progressBar, formatMoney, formatMoneyColored, dim, formatDuration, formatError, renderLogo, institutionName } from "./format.js";
9
10
  export async function runSync() {
10
11
  const ora = (await import("ora")).default;
@@ -26,6 +27,7 @@ export async function runSync() {
26
27
  export async function runLink() {
27
28
  const open = (await import("open")).default;
28
29
  const ora = (await import("ora")).default;
30
+ const readline = await import("readline");
29
31
  const { url, waitForComplete, stop } = startLinkServer();
30
32
  console.log(`\n${heading("Link Account")}\n`);
31
33
  console.log(`Opening Plaid Link in your browser...\n`);
@@ -35,6 +37,37 @@ export async function runLink() {
35
37
  await waitForComplete();
36
38
  stop();
37
39
  spinner.succeed("Bank account linked successfully!");
40
+ // Check if a mortgage was linked and we don't already have a property account
41
+ const db = getDb();
42
+ const hasMortgage = db.prepare(`SELECT 1 FROM accounts WHERE type = 'loan' AND subtype = 'mortgage' LIMIT 1`).get();
43
+ const hasProperty = db.prepare(`SELECT 1 FROM accounts WHERE type = 'other' AND subtype = 'property' LIMIT 1`).get();
44
+ if (hasMortgage && !hasProperty) {
45
+ console.log(`\n${dim("Mortgage detected.")} Track your home value for accurate net worth.`);
46
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
47
+ const ask = (q) => new Promise(resolve => rl.question(q, resolve));
48
+ const listingUrl = (await ask(`${dim("Paste a Redfin URL (or press Enter to skip):")} `)).trim();
49
+ if (listingUrl) {
50
+ const name = (await ask(`${dim("Name (e.g. Primary Residence):")} `)).trim() || "Primary Residence";
51
+ rl.close();
52
+ const propSpinner = ora("Fetching home value...").start();
53
+ try {
54
+ const value = await scrapeRedfinEstimate(listingUrl);
55
+ if (value) {
56
+ addManualAccount(db, name, "asset", value, listingUrl);
57
+ propSpinner.succeed(`${name}: ${rawFormatMoney(value)} — updates automatically on sync.`);
58
+ }
59
+ else {
60
+ propSpinner.fail("Could not determine home value from that URL. Try 'ray add' later.");
61
+ }
62
+ }
63
+ catch {
64
+ propSpinner.fail("Failed to fetch home value. Try 'ray add' later.");
65
+ }
66
+ }
67
+ else {
68
+ rl.close();
69
+ }
70
+ }
38
71
  }
39
72
  export async function showAccounts() {
40
73
  const db = getDb();
@@ -239,6 +272,108 @@ export function showScore() {
239
272
  }
240
273
  console.log();
241
274
  }
275
+ export async function runAdd() {
276
+ const ora = (await import("ora")).default;
277
+ const inquirer = (await import("inquirer")).default;
278
+ const db = getDb();
279
+ const theme = {
280
+ prefix: { idle: " ", done: chalk.green(" ✓") },
281
+ style: { highlight: (text) => chalk.yellowBright(text) },
282
+ };
283
+ console.log(`\n${heading("Add Account")}`);
284
+ console.log(dim(" Track something not linked via Plaid — a home, car, crypto, loan, etc.\n"));
285
+ const { name } = await inquirer.prompt([{ theme,
286
+ type: "input",
287
+ name: "name",
288
+ message: "Name",
289
+ validate: (v) => v.trim() ? true : "Required",
290
+ }]);
291
+ const { type } = await inquirer.prompt([{ theme,
292
+ type: "list",
293
+ name: "type",
294
+ message: "Type",
295
+ choices: [
296
+ { name: "Asset — something you own (adds to net worth)", value: "asset" },
297
+ { name: "Liability — something you owe (subtracts from net worth)", value: "liability" },
298
+ ],
299
+ }]);
300
+ let finalBalance = 0;
301
+ let listingUrl;
302
+ // For assets: offer Redfin auto-tracking
303
+ if (type === "asset") {
304
+ const { redfin } = await inquirer.prompt([{ theme,
305
+ type: "input",
306
+ name: "redfin",
307
+ message: `Redfin URL ${dim("(optional — auto-tracks home value)")}`,
308
+ }]);
309
+ const url = redfin.trim();
310
+ if (url) {
311
+ try {
312
+ const parsed = new URL(url);
313
+ if (!parsed.hostname.includes("redfin")) {
314
+ console.log(chalk.yellow(" Only Redfin URLs are supported."));
315
+ }
316
+ else {
317
+ listingUrl = url;
318
+ const spinner = ora("Fetching Redfin Estimate...").start();
319
+ const scraped = await scrapeRedfinEstimate(url);
320
+ if (scraped) {
321
+ finalBalance = scraped;
322
+ spinner.succeed(`Redfin Estimate: ${chalk.bold(rawFormatMoney(scraped))} ${dim("— updates on each sync")}`);
323
+ }
324
+ else {
325
+ spinner.warn("Could not fetch estimate.");
326
+ listingUrl = undefined;
327
+ }
328
+ }
329
+ }
330
+ catch {
331
+ console.log(chalk.yellow(" Invalid URL."));
332
+ }
333
+ }
334
+ }
335
+ // Manual value if no Redfin
336
+ if (!listingUrl) {
337
+ const { balance } = await inquirer.prompt([{ theme,
338
+ type: "input",
339
+ name: "balance",
340
+ message: "Current value ($)",
341
+ validate: (v) => {
342
+ const n = parseFloat(v.replace(/[$,]/g, ""));
343
+ return isNaN(n) ? "Enter a number" : true;
344
+ },
345
+ }]);
346
+ finalBalance = parseFloat(balance.replace(/[$,]/g, ""));
347
+ }
348
+ addManualAccount(db, name.trim(), type, finalBalance, listingUrl);
349
+ const label = type === "asset" ? chalk.green("asset") : chalk.red("liability");
350
+ console.log(`\n ${chalk.green("+")} ${chalk.bold(name.trim())} ${rawFormatMoney(finalBalance)} ${label}\n`);
351
+ }
352
+ export async function runRemove() {
353
+ const readline = await import("readline");
354
+ const db = getDb();
355
+ const accounts = getManualAccounts(db);
356
+ if (accounts.length === 0) {
357
+ console.log("\nNo manual accounts. Use 'ray add' to create one.");
358
+ return;
359
+ }
360
+ console.log(`\n${heading("Manual Accounts")}\n`);
361
+ for (let i = 0; i < accounts.length; i++) {
362
+ const a = accounts[i];
363
+ const typeLabel = a.type === "loan" || a.type === "credit" ? "liability" : "asset";
364
+ const url = a.listing_url ? dim(` — ${a.listing_url}`) : "";
365
+ console.log(` ${dim(`${i + 1}.`)} ${a.name} ${rawFormatMoney(a.current_balance)} (${typeLabel})${url}`);
366
+ }
367
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
368
+ const answer = (await new Promise(resolve => rl.question(`\n Remove which? (number, or Enter to cancel): `, resolve))).trim();
369
+ rl.close();
370
+ const idx = parseInt(answer, 10) - 1;
371
+ if (isNaN(idx) || idx < 0 || idx >= accounts.length)
372
+ return;
373
+ removeManualAccount(db, accounts[idx].account_id);
374
+ console.log(chalk.green(`\n Removed ${accounts[idx].name}.`));
375
+ console.log();
376
+ }
242
377
  export function showAlerts() {
243
378
  const db = getDb();
244
379
  const alerts = generateAlerts(db);
package/dist/cli/index.js CHANGED
@@ -1,8 +1,20 @@
1
1
  #!/usr/bin/env node
2
+ import { resolve } from "path";
3
+ import { homedir } from "os";
4
+ // --demo flag: use dedicated demo database (must run before config import)
5
+ const isDemoMode = process.argv.includes("--demo");
6
+ if (isDemoMode) {
7
+ process.argv = process.argv.filter(a => a !== "--demo");
8
+ }
2
9
  import { Command } from "commander";
3
10
  import { createRequire } from "module";
4
11
  import { config, isConfigured, useManaged, RAY_PROXY_BASE } from "../config.js";
5
12
  import { helpScreen } from "./format.js";
13
+ // Override config for demo mode (demo DB is unencrypted)
14
+ if (isDemoMode) {
15
+ config.dbPath = resolve(homedir(), ".ray", "data", "demo.db");
16
+ config.dbEncryptionKey = "";
17
+ }
6
18
  const require = createRequire(import.meta.url);
7
19
  const { version } = require("../../package.json");
8
20
  const program = new Command();
@@ -48,6 +60,22 @@ program
48
60
  const { runLink } = await import("./commands.js");
49
61
  await runLink();
50
62
  });
63
+ program
64
+ .command("add")
65
+ .description("Add a manual account (home, car, crypto, etc.)")
66
+ .action(async () => {
67
+ ensureConfigured();
68
+ const { runAdd } = await import("./commands.js");
69
+ await runAdd();
70
+ });
71
+ program
72
+ .command("remove")
73
+ .description("Remove a manual account")
74
+ .action(async () => {
75
+ ensureConfigured();
76
+ const { runRemove } = await import("./commands.js");
77
+ await runRemove();
78
+ });
51
79
  program
52
80
  .command("accounts")
53
81
  .description("Show linked accounts and balances")
@@ -181,6 +209,14 @@ program
181
209
  const { runDoctor } = await import("./doctor.js");
182
210
  await runDoctor();
183
211
  });
212
+ program
213
+ .command("demo")
214
+ .description("Seed a demo database with realistic fake data")
215
+ .action(async () => {
216
+ const demoPath = resolve(homedir(), ".ray", "data", "demo.db");
217
+ const { seedDemoDb } = await import("../demo/seed.js");
218
+ seedDemoDb(demoPath);
219
+ });
184
220
  program
185
221
  .command("completions")
186
222
  .description("Install shell completions")
@@ -189,6 +225,8 @@ program
189
225
  installCompletions();
190
226
  });
191
227
  function ensureConfigured() {
228
+ if (isDemoMode)
229
+ return;
192
230
  if (!isConfigured()) {
193
231
  console.error("Ray is not configured. Run 'ray setup' first.");
194
232
  process.exit(1);
@@ -199,6 +237,8 @@ program.configureHelp({
199
237
  formatHelp: () => helpScreen([
200
238
  { name: "setup", desc: "Configure Ray (API keys, preferences)" },
201
239
  { name: "link", desc: "Link a new financial account via Plaid" },
240
+ { name: "add", desc: "Add a manual account (home, car, crypto, etc.)" },
241
+ { name: "remove", desc: "Remove a manual account" },
202
242
  { name: "sync", desc: "Sync transactions from linked banks" },
203
243
  { name: "accounts", desc: "Show linked accounts and balances" },
204
244
  { name: "status", desc: "Show financial overview" },
@@ -213,6 +253,7 @@ program.configureHelp({
213
253
  { name: "billing", desc: "Manage your Ray subscription" },
214
254
  { name: "update", desc: "Update Ray to the latest version" },
215
255
  { name: "doctor", desc: "Check system health" },
256
+ { name: "demo", desc: "Seed a demo database with fake data" },
216
257
  { name: "completions", desc: "Install shell completions" },
217
258
  ]),
218
259
  });
@@ -3,6 +3,7 @@ import { calculateDailyScore, checkAchievements } from "./scoring/index.js";
3
3
  import { decryptPlaidToken } from "./db/encryption.js";
4
4
  import { config } from "./config.js";
5
5
  import { institutionName } from "./cli/format.js";
6
+ import { refreshPropertyValues, hasListingUrls } from "./property.js";
6
7
  /** Run the daily sync for a single database */
7
8
  export async function runDailySync(db) {
8
9
  const institutions = db
@@ -98,6 +99,15 @@ export async function runDailySync(db) {
98
99
  console.error(` Error syncing ${inst.name}: ${err.message}`);
99
100
  }
100
101
  }
102
+ // Refresh property values from listing URLs if configured
103
+ if (hasListingUrls(db)) {
104
+ try {
105
+ await refreshPropertyValues(db);
106
+ }
107
+ catch {
108
+ // Non-fatal
109
+ }
110
+ }
101
111
  // Snapshot net worth
102
112
  const assets = db
103
113
  .prepare(`SELECT COALESCE(SUM(current_balance), 0) as total FROM accounts WHERE type IN ('depository', 'investment', 'other')`)
@@ -0,0 +1,252 @@
1
+ export declare const institutions: {
2
+ item_id: string;
3
+ access_token: string;
4
+ name: string;
5
+ products: string;
6
+ logo: string;
7
+ primary_color: string;
8
+ }[];
9
+ export declare const accounts: ({
10
+ account_id: string;
11
+ item_id: string;
12
+ name: string;
13
+ official_name: string;
14
+ type: string;
15
+ subtype: string;
16
+ mask: string;
17
+ current_balance: number;
18
+ available_balance: number;
19
+ currency: string;
20
+ balance_limit: null;
21
+ } | {
22
+ account_id: string;
23
+ item_id: string;
24
+ name: string;
25
+ official_name: string;
26
+ type: string;
27
+ subtype: string;
28
+ mask: string;
29
+ current_balance: number;
30
+ available_balance: null;
31
+ currency: string;
32
+ balance_limit: null;
33
+ } | {
34
+ account_id: string;
35
+ item_id: string;
36
+ name: string;
37
+ official_name: string;
38
+ type: string;
39
+ subtype: string;
40
+ mask: string;
41
+ current_balance: number;
42
+ available_balance: number;
43
+ currency: string;
44
+ balance_limit: number;
45
+ } | {
46
+ account_id: string;
47
+ item_id: string;
48
+ name: string;
49
+ official_name: null;
50
+ type: string;
51
+ subtype: string;
52
+ mask: null;
53
+ current_balance: number;
54
+ available_balance: null;
55
+ currency: string;
56
+ balance_limit: null;
57
+ })[];
58
+ export declare const transactions: ({
59
+ transaction_id: string;
60
+ account_id: string;
61
+ amount: number;
62
+ date: string;
63
+ name: string;
64
+ merchant_name: string;
65
+ category: string;
66
+ subcategory: string;
67
+ pending: number;
68
+ payment_channel: string;
69
+ } | {
70
+ transaction_id: string;
71
+ account_id: string;
72
+ amount: number;
73
+ date: string;
74
+ name: string;
75
+ merchant_name: null;
76
+ category: string;
77
+ subcategory: string;
78
+ pending: number;
79
+ payment_channel: string;
80
+ })[];
81
+ export declare const securities: {
82
+ security_id: string;
83
+ name: string;
84
+ ticker: string;
85
+ type: string;
86
+ close_price: number;
87
+ close_price_as_of: string;
88
+ }[];
89
+ export declare const holdings: ({
90
+ account_id: string;
91
+ security_id: string;
92
+ quantity: number;
93
+ value: number;
94
+ cost_basis: number;
95
+ price: number;
96
+ price_as_of: string;
97
+ vested_value: null;
98
+ vested_quantity: null;
99
+ } | {
100
+ account_id: string;
101
+ security_id: string;
102
+ quantity: number;
103
+ value: number;
104
+ cost_basis: number;
105
+ price: number;
106
+ price_as_of: string;
107
+ vested_value: number;
108
+ vested_quantity: number;
109
+ })[];
110
+ export declare const liabilities: ({
111
+ account_id: string;
112
+ type: string;
113
+ interest_rate: number;
114
+ origination_date: null;
115
+ original_balance: null;
116
+ current_balance: number;
117
+ minimum_payment: number;
118
+ next_payment_due: string;
119
+ last_payment_amount: number;
120
+ last_payment_date: string;
121
+ credit_limit: number;
122
+ last_statement_issue_date: string;
123
+ is_overdue: number;
124
+ apr_type: string;
125
+ maturity_date: null;
126
+ loan_type: null;
127
+ property_address: null;
128
+ escrow_balance: null;
129
+ loan_status: null;
130
+ loan_name: null;
131
+ repayment_plan: null;
132
+ expected_payoff_date: null;
133
+ ytd_interest_paid: null;
134
+ ytd_principal_paid: null;
135
+ } | {
136
+ account_id: string;
137
+ type: string;
138
+ interest_rate: number;
139
+ origination_date: string;
140
+ original_balance: number;
141
+ current_balance: number;
142
+ minimum_payment: number;
143
+ next_payment_due: string;
144
+ last_payment_amount: number;
145
+ last_payment_date: string;
146
+ credit_limit: null;
147
+ last_statement_issue_date: null;
148
+ is_overdue: number;
149
+ apr_type: string;
150
+ maturity_date: string;
151
+ loan_type: string;
152
+ property_address: string;
153
+ escrow_balance: number;
154
+ loan_status: string;
155
+ loan_name: string;
156
+ repayment_plan: null;
157
+ expected_payoff_date: string;
158
+ ytd_interest_paid: number;
159
+ ytd_principal_paid: number;
160
+ })[];
161
+ export declare const recurring: ({
162
+ stream_id: string;
163
+ account_id: string;
164
+ merchant_name: string;
165
+ description: string;
166
+ frequency: string;
167
+ category: string;
168
+ subcategory: string;
169
+ avg_amount: number;
170
+ last_amount: number;
171
+ first_date: string;
172
+ last_date: string;
173
+ is_active: number;
174
+ status: string;
175
+ stream_type: string;
176
+ } | {
177
+ stream_id: string;
178
+ account_id: string;
179
+ merchant_name: null;
180
+ description: string;
181
+ frequency: string;
182
+ category: string;
183
+ subcategory: string;
184
+ avg_amount: number;
185
+ last_amount: number;
186
+ first_date: string;
187
+ last_date: string;
188
+ is_active: number;
189
+ status: string;
190
+ stream_type: string;
191
+ })[];
192
+ export declare const budgets: {
193
+ category: string;
194
+ monthly_limit: number;
195
+ period: string;
196
+ }[];
197
+ export declare const goals: {
198
+ name: string;
199
+ target_amount: number;
200
+ current_amount: number;
201
+ target_date: string;
202
+ status: string;
203
+ }[];
204
+ export declare const dailyScores: {
205
+ date: string;
206
+ score: number;
207
+ restaurant_count: number;
208
+ shopping_count: number;
209
+ food_spend: number;
210
+ total_spend: number;
211
+ zero_spend: number;
212
+ no_restaurant_streak: number;
213
+ no_shopping_streak: number;
214
+ on_pace_streak: number;
215
+ }[];
216
+ export declare const achievements: {
217
+ key: string;
218
+ name: string;
219
+ description: string;
220
+ unlocked_at: string;
221
+ }[];
222
+ export declare const netWorthHistory: {
223
+ date: string;
224
+ total_assets: number;
225
+ total_liabilities: number;
226
+ net_worth: number;
227
+ }[];
228
+ export declare const investmentTransactions: {
229
+ investment_transaction_id: string;
230
+ account_id: string;
231
+ security_id: string;
232
+ date: string;
233
+ name: string;
234
+ quantity: number;
235
+ amount: number;
236
+ price: number;
237
+ fees: number;
238
+ type: string;
239
+ subtype: string;
240
+ iso_currency_code: string;
241
+ }[];
242
+ export declare const recurringBills: {
243
+ name: string;
244
+ amount: number;
245
+ day_of_month: number;
246
+ type: string;
247
+ account_id: string;
248
+ }[];
249
+ export declare const memories: {
250
+ content: string;
251
+ category: string;
252
+ }[];