Plutus Pro — Wealth Intelligence — Plutus Pro — 财富智能
v1.0.0Plutus Pro — 财富智能。利用AI驱动的分类功能,实现全面的支出跟踪、多账户对账、税收分类标签、预算预测...
运行时依赖
安装命令
点击复制本土化适配说明
Plutus Pro — Wealth Intelligence — Plutus Pro — 财富智能 安装说明: 安装命令:["openclaw skills install plutus-pro"]
技能文档
Plutus Pro — 全面的财富智能 Plutus 的所有功能,另外还包括税务标签、储蓄率分析、多月预测、损益总结和每笔交易的备注。
Pro 版本与免费版的对比 功能 | Plutus(免费) | Plutus Pro ---------|----------|--------- 交易 | 无限制 | 无限制 类别 | 15 个标准类别 | 15 个标准类别 + 自定义税务标签 预算比较 | | + 百分比提醒 月度趋势 | | + 损益总结 税务类别标签 | | 储蓄率分析 | | 支出预测 | | 1-12 个月的 JSON 导出 | | 完整的结构化数据 | | 盈余/亏损 | | 月度损益总结 | |
步骤 1 — 安装
pip3 install rich --break-system-packages --quiet
步骤 2 — 全面的财富分析(Pro)
```python
import os, re, json, csv
from datetime import datetime, date
from collections import defaultdict
from rich.console import Console
from rich.table import Table
from rich.panel import Panel
from rich import boxconsole = Console() LICENSE_KEY = os.environ.get("LICENSE_KEY", "").strip() if not LICENSE_KEY: console.print(Panel( "[red bold]需要许可密钥[/red bold]\n\n" "获取密钥:[bold cyan]ko-fi.com/occupythemilkyway[/bold cyan]\n\n" "或使用免费版本:[dim]openclaw skills install plutus[/dim]", title="许可密钥", border_style="red" )) raise SystemExit(1)
EXPENSES_FILE = os.environ.get("EXPENSES_FILE", "").strip() EXPENSES_TEXT = os.environ.get("EXPENSES_TEXT", "").strip() BUDGET_RAW = os.environ.get("BUDGET_JSON", "").strip() CURRENCY = os.environ.get("CURRENCY", "USD").upper() REPORT_MONTH = os.environ.get("REPORT_MONTH", "").strip() TAX_CATS_RAW = os.environ.get("TAX_CATEGORIES", "Business,Education") TAX_CATEGORIES = [t.strip() for t in TAX_CATS_RAW.split(",") if t.strip()] try: SAVINGS_GOAL = float(os.environ.get("SAVINGS_GOAL", "0")) except: SAVINGS_GOAL = 0.0 try: FORECAST_MONTHS = min(int(os.environ.get("FORECAST_MONTHS", "3")), 12) except: FORECAST_MONTHS = 3 TODAY = date.today() SYM = {"USD": "$", "EUR": "€", "GBP": "£", "CAD": "CA$"}.get(CURRENCY, "$")
def fmt(a): return f"{SYM}{abs(a):,.2f}"
CATEGORIES = { "Food & Dining": ["coffee", "starbucks", "restaurant", "pizza", "burger", "cafe", "dining", "food", "doordash", "grubhub", "grocery", "groceries", "walmart", "whole foods", "supermarket"], "Transport": ["uber", "lyft", "taxi", "gas", "fuel", "parking", "transit", "metro", "bus", "train", "airline", "flight", "car rental", "toll", "petrol"], "Shopping": ["amazon", "ebay", "etsy", "target", "bestbuy", "clothing", "shoes", "fashion", "zara", "nordstrom", "mall"], "Subscriptions": ["netflix", "spotify", "hulu", "disney", "apple music", "youtube", "prime", "subscription", "membership", "software", "adobe", "microsoft", "google"], "Utilities": ["electric", "electricity", "water", "internet", "phone", "mobile", "cellular", "at&t", "verizon", "comcast", "hydro", "utility"], "Health": ["pharmacy", "doctor", "dentist", "medical", "hospital", "prescription", "medicine", "gym", "fitness", "yoga", "cvs", "walgreens"], "Entertainment": ["movie", "cinema", "theatre", "concert", "ticket", "game", "gaming", "steam", "kindle", "audible", "museum"], "Travel": ["hotel", "airbnb", "hostel", "resort", "booking", "expedia", "trip", "vacation", "tour"], "Education": ["course", "udemy", "coursera", "tuition", "textbook", "training", "workshop", "class", "lesson"], "Home": ["rent", "mortgage", "furniture", "home depot", "lowes", "hardware", "repair", "maintenance", "cleaning"], "Insurance": ["insurance", "premium", "policy", "geico", "allstate", "progressive"], "Business": ["invoice", "client", "freelance", "office", "supplies", "coworking", "advertising", "domain", "hosting"], "Personal Care": ["salon", "haircut", "barber", "spa", "beauty", "cosmetics", "skincare", "makeup", "nails"], "Income / Credit": [], }
def categorise(desc, amount): if amount < 0: return "Income / Credit" dl = desc.lower() for cat, kws in CATEGORIES.items(): if cat == "Income / Credit": continue if any(k in dl for k in kws): return cat return "Other"
def parse_amount(raw): raw = str(raw).strip().lstrip("$£€").replace(",", "") try: return float(raw) except: return None
MONTH_MAP = {"jan": 1, "feb": 2, "mar": 3, "apr": 4, "may": 5, "jun": 6, "jul": 7, "aug": 8, "sep": 9, "oct": 10, "nov": 11, "dec": 12}
def parse_date(raw): raw = str(raw).strip() for fmt_s in ("%Y-%m-%d", "%m/%d/%Y", "%d/%m/%Y", "%m-%d-%Y"): try: return datetime.strptime(raw, fmt_s).date() except: pass import re as _re m = _re.match(r"([A-Za-z]+)\s+(\d{1,2})(?:\s+(\d{4}))?", raw) if m: mon = MONTH_MAP.get(m.group(1)[:3].lower()) if mon: try: return date(int(m.group(3) or TODAY.year), mon, int(m.group(2))) except: pass return None
transactions = [] if EXPENSES_FILE and os.path.exists(EXPENSES_FILE): with open(EXPENSES_FILE, newline="", encoding="utf-8") as fh: reader = csv.DictReader(fh)