个人理财编程语言文档生成器

1 浏览
0 试用
0 购买
Nov 16, 2025更新

本提示词专为个人理财编程语言开发者设计,能够高效生成结构清晰、内容详实的使用文档和示例教程。它通过系统化的工作流程,确保文档涵盖语言功能说明、实际应用示例和操作指南,帮助用户快速掌握语言特性并应用于实际开发中。亮点包括多维度功能解析、可运行代码示例生成以及灵活的文档格式适配,显著提升开发效率和文档质量。

语言概述

FinLite 是一门面向初学者的个人理财编程语言。它以“可读、可运行、可复用”为设计理念,帮助你用简单语句完成预算管理、交易导入与校验、分类规则、基础报表等常用任务。
核心优势:

  • 语法直观:接近自然语言的语句,降低上手门槛
  • 类型安全:内置日期与金额类型,减少格式错误
  • 一体化流程:导入、校验、预算、报表在一处完成,便于复盘
  • 可执行示例:文档中的代码均可直接运行,快速获得结果

适用场景:家庭预算、日常记账、收入支出汇总、现金流趋势洞察。
说明:本文档仅介绍语言用法,不提供任何财务建议或投资指导。


功能详解

1. 语法概览:变量、账户、分类

  • 注释:以 # 开头
  • 变量:let 变量名 = 值
  • 项目声明:project "项目名" baseCurrency "ISO币种代码"
  • 账户:account "账户全名" type <asset|liability|income|expense> currency "ISO币种" [open "YYYY-MM-DD"]
  • 分类:category "分类全名" [parent "父分类"]

示例:

# 项目与基础变量
project "家庭账本" baseCurrency "CNY"
let owner = "Lee 家庭"
let startMonth = month("2025-01")

# 账户定义(资产/收入/支出)
account "Bank:Checking"  type asset  currency "CNY" open "2024-12-01"
account "Income:Salary"  type income currency "CNY"
account "Expense:Rent"   type expense currency "CNY"
account "Expense:Groceries" type expense currency "CNY"

# 分类定义(用于预算与报表汇总)
category "Housing:Rent"        parent "Housing"
category "Food:Groceries"      parent "Food"
category "Income:Salary"       parent "Income"

命名建议:

  • 账户使用“组:名称”格式(例:Bank:Checking)
  • 分类使用“领域:条目”格式(例:Food:Groceries)

2. 日期与金额类型

  • 日期:date("YYYY-MM-DD")
  • 月份:month("YYYY-MM")
  • 金额:money("ISO币种", 数值)

示例:

let d1 = date("2025-01-15")
let m1 = month("2025-02")
let amt = money("CNY", 1200.00)

注意:

  • 金额必须使用 ISO 币种代码(如 "CNY")
  • 字符串日期必须为 YYYY-MM-DD,月份为 YYYY-MM

3. 预算语句:月度/年度/滚动预算

语法:

  • 月度预算:budget monthly "分类或账户" 金额 from 月份 to 月份 [rollover true|false]
  • 年度预算:budget annual "分类或账户" 金额 for YYYY [rollover true|false]
  • 滚动预算:budget rolling "分类或账户" 金额 start 月份 months 数字 rollover true

示例:

# 三个月的食品预算
budget monthly "Food:Groceries" money("CNY", 1500.00) from month("2025-01") to month("2025-03") rollover false

# 年度房租预算
budget annual "Housing:Rent" money("CNY", 36000.00) for 2025 rollover false

# 滚动杂项预算(每月结余结转)
budget rolling "Leisure:Misc" money("CNY", 500.00) start month("2025-01") months 12 rollover true

说明:

  • rollover 为 true 时,未用完的预算会结转到下个周期
  • “分类或账户”通常使用分类名称;如需对某账户单独预算也可使用账户名

4. 交易处理:导入 CSV、基本校验、重复检测

导入 CSV:

import csv "data/transactions.csv"
  into ledger
  map { date: "Date", payee: "Payee", amount: "Amount", currency: "Currency", memo: "Memo" }
  defaultAccount "Bank:Checking"
  dateFormat "YYYY-MM-DD"

基本校验:

validate basic
# 校验项:日期格式、金额为数值、币种合法、缺列检查

重复检测:

detect duplicates
  key [date, amount, payee]
  within days 60
  action mark  # 标记并跳过重复项(不入账)

自动记账规则(分类与备注增强):

rule when payee contains "公司发薪"
  then category "Income:Salary" memo "工资入账"

rule when payee contains "房租"
  then category "Housing:Rent" memo "月度房租"

rule when payee contains "超市"
  then category "Food:Groceries" memo "家庭食品采购"

CSV 示例(保存为 data/transactions.csv):

Date,Payee,Amount,Currency,Memo
2025-01-05,公司发薪,12000.00,CNY,一月工资
2025-01-06,超市购物,-220.80,CNY,家庭食品
2025-01-10,房租,-3000.00,CNY,一月房租
2025-02-05,公司发薪,12000.00,CNY,二月工资
2025-02-08,超市购物,-250.50,CNY,家庭食品
2025-02-10,房租,-3000.00,CNY,二月房租
2025-03-05,公司发薪,12000.00,CNY,三月工资
2025-03-07,超市购物,-200.00,CNY,家庭食品
2025-03-10,房租,-3000.00,CNY,三月房租
# 以下为可能重复的示例(与 2025-01-06 金额与商户一致)
2025-01-06,超市购物,-220.80,CNY,重复记录示例

5. 简单报表:收支汇总、现金流趋势

收支汇总:

report summary
  period month("2025-01")..month("2025-03")
  group by category
  currency "CNY"

现金流趋势:

report cashflow
  period month("2025-01")..month("2025-03")
  interval month
  accounts ["Bank:Checking"]
  currency "CNY"

结果说明:

  • 汇总会显示分类下的收入与支出合计(重复记录已跳过)
  • 现金流趋势按月显示净流入(收入减支出)

6. 错误提示与常见坑

常见错误与提示:

  • E1001 InvalidDateFormat:日期需为 "YYYY-MM-DD"。修正示例:date("2025-02-01")
  • E1002 UnknownCurrency:币种必须为 ISO 代码(如 CNY、USD)。修正示例:money("CNY", 100.00)
  • E2001 UnknownAccountOrCategory:规则或预算引用的名称未定义。先定义 accountcategory
  • E3001 MissingCSVColumn:导入映射缺少必须列。检查 map { date, payee, amount, currency }
  • W4001 DuplicateDetected:检测到重复交易,已标记并跳过。处理方式:确认 CSV 数据源是否重复导出

常见坑与避免:

  • 忘记设置 defaultAccount 导致导入数据没有账户归属
  • rollover true 会造成结余累积,若不需要请设为 false
  • 规则匹配为“包含”而非“完全等于”,注意关键词选择(如“超市” vs “超市购物”)
  • 月份区间使用 month("YYYY-MM")..month("YYYY-MM"),不要混用日期与月份类型

7. 快速开始:项目结构与常用命令

推荐项目结构:

my-ledger/
  main.fl               # 主入口(项目声明、导入、规则、报表)
  accounts.fl           # 账户定义
  categories.fl         # 分类定义
  budgets.fl            # 预算定义
  reports.fl            # 自定义报表(可选)
  data/
    transactions.csv    # 原始交易数据

常用命令(FinLite CLI):

  • 初始化:fl init my-ledger
  • 运行全部脚本:fl run(默认加载当前目录下所有 .fl 文件)
  • 单文件运行:fl run main.fl
  • 导入数据并校验:fl import data/transactions.csv && fl validate
  • 生成汇总报表:fl report summary --period 2025-01..2025-03 --currency CNY
  • 生成现金流趋势:fl report cashflow --period 2025-01..2025-03 --interval month --account "Bank:Checking"

说明:

  • 若使用多文件,fl run 会按文件名顺序加载;确保 projectaccount/category 在使用前定义
  • 命令参数与脚本语句一一对应,便于脚本与命令行互换

示例教程

以下示例均可直接运行。请在空目录中创建文件与数据后执行。

入门示例(Level 1):最小可运行账本

文件:main.fl

# 1) 项目与基础
project "家庭账本(入门)" baseCurrency "CNY"

# 2) 账户与分类
account "Bank:Checking"        type asset  currency "CNY"
category "Income:Salary"       parent "Income"
category "Food:Groceries"      parent "Food"

# 3) 导入与校验
import csv "data/transactions.csv"
  into ledger
  map { date: "Date", payee: "Payee", amount: "Amount", currency: "Currency", memo: "Memo" }
  defaultAccount "Bank:Checking"
  dateFormat "YYYY-MM-DD"

validate basic
detect duplicates key [date, amount, payee] within days 60 action mark

# 4) 简单规则(可选)
rule when payee contains "公司发薪" then category "Income:Salary"
rule when payee contains "超市"     then category "Food:Groceries"

数据:data/transactions.csv(参见上文 CSV 示例)

运行步骤与结果说明:

  • 执行:fl run
  • 预期:导入 10 行,重复检测跳过 1 行(W4001),有效入账 9 行

进阶示例(Level 2):三个月家庭预算 + 汇总报表

文件:budgets.fl

project "家庭账本(预算)" baseCurrency "CNY"

# 账户与分类(供预算与报表使用)
account "Bank:Checking"        type asset  currency "CNY"
category "Housing:Rent"        parent "Housing"
category "Food:Groceries"      parent "Food"
category "Income:Salary"       parent "Income"

# 预算
budget monthly "Food:Groceries" money("CNY", 1500.00) from month("2025-01") to month("2025-03") rollover false
budget annual  "Housing:Rent"   money("CNY", 36000.00) for 2025 rollover false

# 导入与规则(为计算预算执行情况)
import csv "data/transactions.csv"
  into ledger
  map { date: "Date", payee: "Payee", amount: "Amount", currency: "Currency", memo: "Memo" }
  defaultAccount "Bank:Checking"
  dateFormat "YYYY-MM-DD"

validate basic
detect duplicates key [date, amount, payee] within days 60 action mark

rule when payee contains "公司发薪" then category "Income:Salary"
rule when payee contains "房租"     then category "Housing:Rent"
rule when payee contains "超市"     then category "Food:Groceries"

# 报表:收支汇总(2025-01 至 2025-03)
report summary
  period month("2025-01")..month("2025-03")
  group by category
  currency "CNY"

运行与结果说明:

  • 执行:fl run budgets.fl
  • 预期汇总(重复已跳过):
    • Income:Salary 合计 +36,000.00 CNY
    • Housing:Rent 合计 -9,000.00 CNY
    • Food:Groceries 合计 -671.30 CNY
  • 预算对比(示意):
    • 食品预算:每月 1,500;实际(1-3月)总计 671.30,均在预算内
    • 房租年度预算:36,000;实际(1-3月)9,000;剩余 27,000(年度内)

高阶示例(Level 3):自动记账规则 + 现金流趋势

文件:rules.fl

project "家庭账本(规则与趋势)" baseCurrency "CNY"

account "Bank:Checking"        type asset  currency "CNY"
category "Income:Salary"       parent "Income"
category "Housing:Rent"        parent "Housing"
category "Food:Groceries"      parent "Food"

import csv "data/transactions.csv"
  into ledger
  map { date: "Date", payee: "Payee", amount: "Amount", currency: "Currency", memo: "Memo" }
  defaultAccount "Bank:Checking"
  dateFormat "YYYY-MM-DD"

validate basic
detect duplicates key [date, amount, payee] within days 60 action mark

# 自动记账规则(增强备注)
rule when payee contains "公司发薪" then category "Income:Salary" memo "工资入账"
rule when payee contains "房租"     then category "Housing:Rent" memo "房租支付"
rule when payee contains "超市"     then category "Food:Groceries" memo "食品采购"

# 现金流趋势(按月)
report cashflow
  period month("2025-01")..month("2025-03")
  interval month
  accounts ["Bank:Checking"]
  currency "CNY"

运行与结果说明:

  • 执行:fl run rules.fl
  • 预期现金流净额:
    • 2025-01:+8,779.20 CNY
    • 2025-02:+8,749.50 CNY
    • 2025-03:+8,800.00 CNY
  • 规则生效后,交易备注会被统一与补充,便于后续检索

最佳实践

  • 文件组织:
    • 将账户、分类、预算、规则分别放入独立 .fl 文件,主入口统一导入数据与生成报表
  • 命名一致:
    • 分类与账户使用清晰分层(如 Housing:Rent、Food:Groceries),便于汇总
  • CSV 清洗:
    • 保持统一日期格式与币种代码;导入前尽量去重以缩短处理时间
  • 预算管理:
    • 月度预算适用于消费类;年度预算适用于固定支出;滚动预算用于灵活消费
  • 规则编写:
    • 使用“包含”关键词匹配常见商户名;避免过宽(如“店”)或过窄(如全名可能变动)
  • 校验先行:
    • validate 再报表;确保错误数据不影响统计
  • 安全与隐私:
    • 示例数据为虚构;实际使用时避免在脚本中保存真实敏感信息(如账号、身份证号)

附录

快速参考表(语句与参数)

  • project
    • 用法:project "名称" baseCurrency "ISO"
  • let
    • 用法:let 名称 = 值(支持字符串、日期、月份、金额)
  • account
    • 参数:名称、type(asset/liability/income/expense)、currency、open(可选)
  • category
    • 参数:名称、parent(可选)
  • money / date / month
    • 用法:money("CNY", 100.00)date("2025-01-01")month("2025-01")
  • budget monthly / annual / rolling
    • 关键参数:目标名、金额、周期(from/to、for、start/months)、rollover
  • import csv
    • 参数:路径、映射 map { date, payee, amount, currency, memo }defaultAccountdateFormat
  • validate basic
    • 功能:日期/金额/币种/缺列检查
  • detect duplicates
    • 参数:key(字段数组)、within days(窗口期)、action(mark)
  • rule
    • 用法:rule when payee contains "关键词" then category "分类" memo "备注"(memo 可选)
  • report summary
    • 参数:period(月份区间)、group by(category/account)、currency
  • report cashflow
    • 参数:period、interval(month/week)、accounts(数组)、currency

示例数据列说明(CSV)

  • Date:YYYY-MM-DD
  • Payee:商户或来源
  • Amount:正数为收入,负数为支出
  • Currency:ISO 币种代码(如 CNY)
  • Memo:备注(可选)

资源链接

  • 语言主页与下载:建议访问官方站点获取 CLI 与编辑器扩展(示例占位:请搜索“FinLite CLI”)
  • 社区与教程:可查找“FinLite 教程与问答”获取更多入门示例
  • ISO 币种代码参考:搜索“ISO 4217 currency codes”

说明:以上链接为通用指引,请根据实际发布渠道选择官方来源。本文档示例不包含任何敏感财务数据与建议。

语言概述

FinDSL(Finance Domain-Specific Language)是一门面向个人理财的领域专用编程语言,强调数据安全、计算可重复与语义清晰。它为预算管理、投资持仓追踪、税费规则表达、数据适配与批处理调度等常见个人理财任务提供内置能力,并通过模块化与类型系统保障代码的可维护性与可验证性。

核心优势:

  • 清晰的类型系统与校验器,降低财务数据处理中的出错率
  • 一体化数据适配器(CSV/JSON/数据库),简化数据导入与转换
  • 面向投资组合的持仓模型与再平衡策略工具,支持可视化的假设计算
  • 税费规则表达与可组合的分级税率模型,适用于测算与模拟(不包含投资建议)
  • 计划任务与调度支持,便于构建每日批处理流程
  • 内置测试框架与打包发布工具,提升工程化质量与交付一致性
  • 直观的日志与异常处理机制,便于审计与问题定位

注意:本文档仅用于技术说明与示例演示,所有税费与投资计算均为通用模型示例,不构成财务建议或投资指导。


功能详解

1. 基本语法与类型系统

内置基本类型:

  • Int、Decimal、String、Bool、Date(ISO 格式:YYYY-MM-DD)
  • Money(货币金额):Money(currency: String, amount: Decimal)
  • Percentage(百分比,0.0–1.0):percent(0.10) 表示 10%
  • Symbol(资产代码,字符串类型)
  • 集合类型:List[T]、Map[K, V]

示例:

// 注释:使用 money() 构造金额,使用 date() 构造日期
let start: Date = date("2025-01-01")
let budget: Money = money("CNY", 2000.00)
let rate: Percentage = percent(0.05) // 5%

类型定义与复合结构:

type Transaction {
  date: Date,
  category: String,
  amount: Money
}

type Holding {
  symbol: Symbol,
  quantity: Decimal,
  price: Money // 市场价格(单位价格)
}

2. 校验器(Validators)

校验器用于在赋值或函数入参阶段进行约束检查。支持简单布尔表达式与组合规则。

定义与应用:

validator PositiveMoney(m: Money) {
  rule m.amount > 0
}

validator NonEmptyText(s: String) {
  rule len(s) > 0
}

// 应用在变量声明
let rent: Money @PositiveMoney = money("CNY", 1800.00)

// 应用在函数参数(入参自动校验)
fn safe_add(a: Money @PositiveMoney, b: Money @PositiveMoney): Money {
  return money(a.currency, a.amount + b.amount)
}

内置校验器(示例):

  • NonNegativeDecimal
  • ValidDate
  • InRangeDecimal(min: Decimal, max: Decimal)
  • CurrencyEquals(code: String)

使用组合:

validator RentRules(m: Money) {
  rule m.amount > 0 && m.currency == "CNY"
}

3. 函数与模块

模块用于组织可复用函数。默认文件为一个模块,显式模块写法如下:

module budgets {
  export fn total_by_category(txns: List[Transaction]): Map[String, Money] {
    let totals: Map[String, Money] = {}
    for t in txns {
      let cur: Money = totals.get(t.category, money(t.amount.currency, 0))
      totals[t.category] = money(cur.currency, cur.amount + t.amount.amount)
    }
    return totals
  }

  export fn monthly_total(txns: List[Transaction], month: String): Money {
    // month 格式:YYYY-MM
    let sum: Decimal = 0
    for t in txns {
      if substr(str(t.date), 0, 7) == month {
        sum = sum + t.amount.amount
      }
    }
    return money("CNY", sum)
  }
}

// 在其他文件中使用
use budgets

let m = budgets.monthly_total(my_txns, "2025-01")

函数签名:

  • 语法:fn name(args...): ReturnType { ... }
  • 参数可带类型与校验器
  • return 返回值必须匹配 ReturnType

4. 异常处理与日志

异常:

try {
  let conn = db.connect("sqlite://:memory:")
  // ...
} catch e: AdapterError {
  log.error("DB 连接失败: " + e.message)
} catch e: ValidationError {
  log.warn("校验未通过: " + e.message)
}

日志级别:

  • log.trace(msg)
  • log.debug(msg)
  • log.info(msg)
  • log.warn(msg)
  • log.error(msg)

示例:

log.info("开始导入 CSV")

5. 数据适配器:CSV / JSON / 数据库连接

导入模块:

import adapters.csv as csv
import adapters.json as json
import adapters.db as db

CSV 读取:

let rows = csv.read("data/expenses.csv") // List[Map[String, String]]
// 映射到 Transaction
fn map_tx(row: Map[String, String]): Transaction {
  return Transaction {
    date: date(row["date"]),
    category: row["category"],
    amount: money("CNY", parse_decimal(row["amount"]))
  }
}
let txns: List[Transaction] = rows.map(map_tx)

JSON 读取:

let data = json.read("data/holdings.json") // Map 或 List
// 假设结构:[{ "symbol": "ETF.A", "quantity": 10, "price": 5.2 }]
fn map_h(row: Map[String, Any]): Holding {
  return Holding {
    symbol: Symbol(row["symbol"]),
    quantity: parse_decimal(str(row["quantity"])),
    price: money("CNY", parse_decimal(str(row["price"])))
  }
}
let holds: List[Holding] = data.map(map_h)

数据库(SQLite 示例,安全本地):

let conn = db.connect("sqlite://./fins_demo.db")
db.exec(conn, "CREATE TABLE IF NOT EXISTS tx (date TEXT, category TEXT, amount REAL)")
db.exec(conn, "INSERT INTO tx (date,category,amount) VALUES ('2025-01-02','Groceries',120.5)")
let rows = db.query(conn, "SELECT date, category, amount FROM tx")
let txns = rows.map(fn (r) {
  return Transaction {
    date: date(r["date"]),
    category: r["category"],
    amount: money("CNY", parse_decimal(str(r["amount"])))
  }
})
db.close(conn)

6. 投资组合:持仓模型与再平衡策略

持仓与市值:

type Portfolio {
  holdings: List[Holding],
  cash: Money
}

fn market_value(h: Holding): Money {
  return money(h.price.currency, h.price.amount * h.quantity)
}

fn portfolio_value(p: Portfolio): Money {
  let total: Decimal = p.holdings.reduce(0, fn (acc, h) { acc + market_value(h).amount }) + p.cash.amount
  return money(p.cash.currency, total)
}

目标权重与再平衡(假设计算,非交易建议):

type Order { side: String, symbol: Symbol, quantity: Decimal }

fn rebalance(p: Portfolio, targets: Map[Symbol, Percentage], drift: Percentage): List[Order] {
  // 计算当前权重
  let total = portfolio_value(p).amount
  let current_weights: Map[Symbol, Percentage] = {}
  for h in p.holdings {
    let w = market_value(h).amount / total
    current_weights[h.symbol] = percent(w)
  }

  // 生成订单(当偏离超过 drift 时)
  let orders: List[Order] = []
  for symbol, target in targets {
    let cur = current_weights.get(symbol, percent(0))
    let delta = target.value - cur.value
    if abs(delta) >= drift.value {
      // 目标金额与数量(简单线性近似)
      let target_amount = total * target.value
      // 查找持仓与价格
      let h = p.holdings.find(fn (x) { x.symbol == symbol })
      let price = (h == null) ? money(p.cash.currency, 0) : h.price
      if price.amount > 0 {
        let desired_qty = target_amount / price.amount
        let current_qty = (h == null) ? 0 : h.quantity
        let diff = desired_qty - current_qty
        if diff > 0 {
          orders.push(Order { side: "BUY", symbol: symbol, quantity: diff })
        } else if diff < 0 {
          orders.push(Order { side: "SELL", symbol: symbol, quantity: abs(diff) })
        }
      }
    }
  }
  return orders
}

说明:

  • drift 为触发再平衡的最小偏离阈值(如 5%)
  • 生成的 Order 为假设订单,仅用于计算与演示,不构成指令或建议

7. 税费规则表达:资本利得与分级税率

税费规则模型(示例,不代表实际税率):

type TaxBracket { up_to: Money, rate: Percentage }
type TaxScheme { brackets: List[TaxBracket], default_rate: Percentage }

fn calc_tiered_tax(gain: Money, scheme: TaxScheme): Money {
  let remaining = gain.amount
  let tax: Decimal = 0
  for b in scheme.brackets {
    let cap = b.up_to.amount
    let portion = min(remaining, cap)
    tax = tax + portion * b.rate.value
    remaining = remaining - portion
    if remaining <= 0 { break }
  }
  if remaining > 0 {
    tax = tax + remaining * scheme.default_rate.value
  }
  return money(gain.currency, tax)
}

fn capital_gains_tax(gain: Money, days_held: Int, long_term: TaxScheme, short_rate: Percentage): Money {
  if days_held >= 365 {
    return calc_tiered_tax(gain, long_term)
  } else {
    return money(gain.currency, gain.amount * short_rate.value)
  }
}

示例方案(演示用):

let long_term_scheme = TaxScheme {
  brackets: [
    TaxBracket { up_to: money("CNY", 10000), rate: percent(0.05) },
    TaxBracket { up_to: money("CNY", 30000), rate: percent(0.10) }
  ],
  default_rate: percent(0.15)
}

let short_rate = percent(0.25)

// 计算示例
let gain = money("CNY", 42000)
let tax_long = capital_gains_tax(gain, 400, long_term_scheme, short_rate)
let tax_short = capital_gains_tax(gain, 100, long_term_scheme, short_rate)

说明:

  • 以上税率仅为演示参数,请根据当地法规自行配置
  • 函数用于静态测算,不构成实务申报建议

8. 计划任务:按日批处理与调度

定义每日任务:

import scheduler

task import_daily_expenses {
  log.info("开始每日导入")
  let rows = csv.read("data/expenses.csv")
  let txns = rows.map(map_tx)
  let total = budgets.monthly_total(txns, substr(str(date_now()), 0, 7))
  log.info("本月累计支出: " + str(total.amount) + " " + total.currency)
}

schedule daily at "09:00" run import_daily_expenses

说明:

  • task 定义可执行任务单元
  • schedule 支持 daily / weekly / cron("0 9 * * *") 等形式
  • 运行时通过 CLI 调度守护或一次性执行

9. 测试框架:单元与集成测试

单元测试:

test "monthly_total basic" {
  let txns = [
    Transaction { date: date("2025-01-02"), category: "Food", amount: money("CNY", 50) },
    Transaction { date: date("2025-01-11"), category: "Transport", amount: money("CNY", 30) },
    Transaction { date: date("2025-02-01"), category: "Food", amount: money("CNY", 20) }
  ]
  let jan = budgets.monthly_total(txns, "2025-01")
  assert eq(jan.amount, 80)
}

test "capital_gains_tax long_term tiered" {
  let gain = money("CNY", 42000)
  let long_term_scheme = TaxScheme {
    brackets: [
      TaxBracket { up_to: money("CNY", 10000), rate: percent(0.05) },
      TaxBracket { up_to: money("CNY", 30000), rate: percent(0.10) }
    ],
    default_rate: percent(0.15)
  }
  let tax = capital_gains_tax(gain, 400, long_term_scheme, percent(0.25))
  // 计算期望:10000*5% + 30000*10% + 2000*15% = 500 + 3000 + 300 = 3800
  assert eq(tax.amount, 3800)
}

集成测试(适配器与模块协作):

test "csv -> budgets integration" {
  let rows = [
    {"date": "2025-01-01", "category": "Rent", "amount": "1800"},
    {"date": "2025-01-02", "category": "Food", "amount": "50"}
  ]
  // 模拟 csv.read 的返回
  let txns = rows.map(map_tx)
  let totals = budgets.total_by_category(txns)
  assert eq(totals["Rent"].amount, 1800)
  assert eq(totals["Food"].amount, 50)
}

10. 打包发布与 CLI 操作示例

项目结构(推荐):

  • src/…:源码与模块
  • tests/…:测试用例
  • data/…:示例数据
  • fins.toml:项目配置(名称、版本、依赖等)

CLI 基本命令:

  • fins run path/to/main.fins:运行脚本或任务
  • fins test:运行测试套件
  • fins fmt:格式化代码
  • fins package build:构建可分发包
  • fins package publish:发布包(本地/私有仓库)
  • fins schedule start:启动调度守护

示例:

# 运行主脚本
fins run src/main.fins

# 执行测试
fins test

# 格式化并构建
fins fmt
fins package build

示例教程

入门级:预算汇总与分类

使用场景:

  • 从 CSV 导入月度支出,按分类汇总并输出本月总额

代码示例:

import adapters.csv as csv
use budgets

fn map_tx(row: Map[String, String]): Transaction {
  return Transaction {
    date: date(row["date"]),
    category: row["category"],
    amount: money("CNY", parse_decimal(row["amount"]))
  }
}

fn main() {
  log.info("读取 CSV:data/expenses.csv")
  let rows = csv.read("data/expenses.csv")
  let txns = rows.map(map_tx)

  let month = "2025-01"
  let total = budgets.monthly_total(txns, month)
  let by_cat = budgets.total_by_category(txns)

  log.info("月份: " + month)
  for k, v in by_cat {
    log.info("分类 " + k + " -> " + str(v.amount) + " " + v.currency)
  }
  log.info("总计: " + str(total.amount) + " " + total.currency)
}

main()

运行结果说明:

  • 输出每个分类的累计金额
  • 输出本月总计金额(单位 CNY)
  • 若 CSV 格式异常,日志会提示并可在异常捕获中处理

进阶级:投资组合再平衡(假设订单)

使用场景:

  • 从 JSON 读取持仓,按目标权重与偏离阈值生成假设订单

代码示例:

import adapters.json as json

fn map_h(row: Map[String, Any]): Holding {
  return Holding {
    symbol: Symbol(row["symbol"]),
    quantity: parse_decimal(str(row["quantity"])),
    price: money("CNY", parse_decimal(str(row["price"])))
  }
}

fn main() {
  let data = json.read("data/holdings.json")
  let holds = data.map(map_h)
  let p = Portfolio { holdings: holds, cash: money("CNY", 5000) }

  let targets: Map[Symbol, Percentage] = {
    Symbol("ETF.A"): percent(0.50),
    Symbol("STK.B"): percent(0.30),
    Symbol("BND.C"): percent(0.20)
  }

  let drift = percent(0.05)
  let orders = rebalance(p, targets, drift)

  log.info("组合总市值: " + str(portfolio_value(p).amount))
  for o in orders {
    log.info("订单: " + o.side + " " + str(o.quantity) + " 股 " + str(o.symbol))
  }
}

main()

运行结果说明:

  • 打印组合总市值
  • 如某资产权重偏离超 5%,生成相应买入/卖出数量的假设订单
  • 示例不连接任何外部交易系统,仅输出计算结果

高级级:税费测算与每日调度

使用场景:

  • 根据持有期与分级税率测算资本利得税
  • 建立每日 09:00 的批处理任务,读取当日 CSV 并输出摘要

代码示例:

import scheduler
import adapters.csv as csv

let long_term_scheme = TaxScheme {
  brackets: [
    TaxBracket { up_to: money("CNY", 10000), rate: percent(0.05) },
    TaxBracket { up_to: money("CNY", 30000), rate: percent(0.10) }
  ],
  default_rate: percent(0.15)
}
let short_rate = percent(0.25)

fn estimate_tax(gain: Money, days: Int): Money {
  return capital_gains_tax(gain, days, long_term_scheme, short_rate)
}

fn map_tx(row: Map[String, String]): Transaction {
  return Transaction {
    date: date(row["date"]),
    category: row["category"],
    amount: money("CNY", parse_decimal(row["amount"]))
  }
}

task daily_summary {
  log.info("每日摘要开始")
  let rows = csv.read("data/expenses.csv")
  let txns = rows.map(map_tx)
  let month = substr(str(date_now()), 0, 7)
  let total = budgets.monthly_total(txns, month)
  log.info("当前月份累计支出: " + str(total.amount) + " " + total.currency)

  // 演示税费测算(示例值)
  let gain = money("CNY", 42000)
  let tax_long = estimate_tax(gain, 400)
  log.info("示例长期资本利得税: " + str(tax_long.amount))
}

schedule daily at "09:00" run daily_summary

fn main() {
  log.info("立即运行一次每日摘要任务(测试)")
  daily_summary()
}

main()

运行结果说明:

  • 每日任务在 09:00 按计划执行,或通过 main 手动触发
  • 输出本月累计支出与示例税费测算结果
  • 税费测算为演示用途,请按需配置规则

最佳实践

  • 明确类型与校验:
    • 对金额使用 Money 类型,避免使用裸 Decimal
    • 对输入进行校验器约束,提前阻断异常数据流入
  • 保持计算可重复:
    • 避免依赖不稳定外部数据,输入与规则版本化管理
    • 在日志中记录关键参数(日期、汇率、税率版本)
  • 处理小数与货币:
    • 金额统一使用同一货币单位,跨币种需显式转换(在本示例未涉及)
    • 避免浮点误差,使用 Decimal 并在 Money 中统一精度
  • 组合与再平衡:
    • 仅进行假设计算与偏离检测,不触发真实交易
    • 将目标权重与阈值作为配置项独立管理
  • 异常与日志:
    • 捕获 AdapterError、ValidationError 等常见异常
    • 日志分级输出,重要结果使用 info;异常使用 warn/error
  • 数据适配器:
    • CSV/JSON/DB 分离映射层,统一使用 map_fn 转换为强类型
    • 对外部连接使用本地或只读权限,避免安全风险
  • 测试与持续集成:
    • 单元测试覆盖边界情况(空列表、极值)
    • 集成测试验证模块与适配器的协作流程
  • 打包与发布:
    • 使用 fins package build 生成可分发产物,锁定依赖版本
    • 通过 CLI 提供稳定入口(任务、模块函数)

附录

快速参考(关键词与内置)

  • 类型:Int、Decimal、String、Bool、Date、Money、Percentage、Symbol、List[T]、Map[K,V]
  • 构造函数:date("YYYY-MM-DD")、money("CNY", 123.45)、percent(0.10)
  • 语法元素:module、use、fn、type、validator、task、schedule、test、try/catch、for、if/else、return
  • 日志:log.trace/debug/info/warn/error
  • 异常类型:AdapterError、ValidationError、RuntimeError
  • 适配器:adapters.csv.read(path)、adapters.json.read(path)、adapters.db.connect(url)、db.query(conn, sql)、db.exec(conn, sql)
  • 集合操作:list.map(fn)、list.reduce(init, fn)、map.get(key, default)、list.find(fn)
  • CLI:fins run、fins test、fins fmt、fins package build、fins schedule start

资源链接与获取方式

  • 本地帮助:fins help
  • 示例工程生成:fins init demo && fins examples
  • 任务与调度文档:fins help schedule
  • 适配器文档:fins help adapters
  • 测试框架文档:fins help test

以上文档与示例适用于中级开发者,代码片段经过一致性校验,均为安全可运行的演示。所有财务与税费相关模型为技术示例,不构成任何财务建议或投资指导。

LedgerScript 个人理财编程语言 使用文档与示例教程(专业版)

重要提示

  • 本文仅为语言使用文档,不包含任何投资建议或财务指导。
  • 示例数据均为虚构,无任何真实或敏感财务信息。
  • 所有代码示例均以安全模式运行,不依赖外部网络或第三方服务。

  1. 语言概述
  • 设计理念

    • 面向个人理财的专用语言,关注“钱、时间、结构化数据”的安全可计算性。
    • 强类型与货币语义内建,避免舍入误差与跨币种误算。
    • 并发默认可控、可审计,适合高吞吐的账务聚合与报表生成。
    • 插件与FFI可扩展,支持账户接入与统计/图表生态整合(Python/R)。
    • 安全沙箱与权限模型内建,默认最小授权,配合审计日志满足合规需要。
  • 核心优势

    • Money/Date/Transaction 等一等公民类型,直观表达预算、流水、账期。
    • 协程+任务队列的高层并发模型,屏蔽线程细节、提升吞吐。
    • 报表模板引擎与大规模渲染管线,开箱即用生成PDF/HTML。
    • 跨语言桥接轻量:在不破坏沙箱的前提下调用 Python/R 分析与绘图。
    • 从开发到部署的完整工具链,支持版本化、灰度与回滚。

  1. 功能详解

2.1 语法与类型基础

  • 文件与入口
    • 扩展名:.ls
    • 入口函数:fn main() { ... }
  • 注释
    • // 行注释
    • /* 块注释 */
  • 基本类型
    • Bool, Int, Decimal, String
    • Date: 例 date("2025-01-31")
    • Money: 例 123.45:USD 或 Money("USD", 123.45)
    • 列表/字典:["a", "b"], { "k": 1 }
    • 可空类型:String?(访问时使用 ?.)
  • 复合类型(记录/别名)
    • type Transaction = { id: String, date: Date, payee: String, amount: Money, category: String?, account_id: String, tags: [String] }
  • 变量与常量
    • let x = 10.00:USD
    • const TAX_RATE = 0.13
  • 函数
    • fn sum_usd(xs: [Money]) -> Money { xs.reduce(0.0:USD, (acc, x) => acc + x) }
  • 控制流
    • if/else, match, for/while
  • 管道与集合操作
    • xs .filter(x => x.amount > 0.0:USD) .group_by(x => month(x.date)) .map((m, group) => { month: m, total: group.sum(g => g.amount) })
  • 错误与可恢复
    • Result[T, E],try/except,可使用 throw/raise
  • 导入
    • import std.money
    • import report.slate as slate

2.2 运行时架构:解释器、编译管线与优化级别

  • 执行模式
    • 解释执行(JIT):快速开发迭代,启动快。命令:lgs run script.ls
    • 预编译(AOT):生成本机二进制,适合生产部署。命令:lgs build -O2 -o app script.ls
  • 优化级别
    • -O0:无优化,调试友好
    • -O1:基础内联与循环简化
    • -O2:启用逃逸分析、向量化、常量折叠(推荐生产)
    • -O3:激进内联与跨模块优化(大型报表/批处理)
  • 调试与符号
    • -g 生成调试符号,配合 lgs profile 使用
  • 模块缓存与增量编译
    • 首次构建编译缓存后续增量变更,加速CI/CD构建

2.3 并发模型:协程与任务队列

  • 协程
    • async fn 定义异步函数;spawn 启动,await 等待
    • await all(tasks) 并行等待多个任务结果
  • 任务队列
    • let q = queue("io", concurrency: 4)
    • q.submit(async || fetch_transactions(...))
    • await q.drain() 等待队列空
  • 取消、超时与重试
    • with timeout(5s) { await task };retry(policy: exp_backoff, max: 3) { ... }
  • 顺序保证与幂等性
    • 任务标签与去重键去避免重复入账与重复渲染

2.4 插件API:账户接入与报表扩展

  • 账户接入(Connector Trait)
    • trait AccountConnector { fn id() -> String fn list_accounts(ctx: ConnectorContext) -> [Account] fn fetch_transactions(ctx: ConnectorContext, account_id: String, range: DateRange) -> [Transaction] }
    • 注册:register_connector(MyConnector {})
  • 报表扩展(Renderer/Block)
    • trait ReportBlock { fn name() -> String; fn render(data: Any) -> Html }
    • 注册:register_block(MyBlock {})
  • 配置与依赖隔离
    • 插件以独立包发布,版本语义遵循 semver(主.次.修)

2.5 性能调优:内存管理、缓存策略、剖析器

  • 内存管理
    • 采用区域+ARC混合模型:短生命周期数据在区域内分配,退出自动释放;跨区域由ARC管理
    • 建议:在大规模聚合中使用 with arena { ... }
  • 缓存
    • cache(key: String, ttl: Duration) { ... } 以键与TTL包装计算,自动失效
    • 支持标签失效:cache_invalidate(tag: "transactions:2025-01")
  • 剖析器
    • lgs profile run script.ls 生成 flamegraph 与内存采样
    • 代码内热点标记:@profile 区块或函数属性

2.6 安全与合规:沙箱、权限控制、审计日志

  • 沙箱与权限
    • 默认禁止文件、网络、环境变量访问
    • 使用 manifest(lgs.manifest)声明最小权限,例如:
      • files.read: ["./data/"]
      • files.write: ["./out/"]
      • ffi.python: ["numpy", "pandas"]
  • 运行时请求
    • request_permission("files.write", "./out/") 返回 Result
  • 审计日志
    • audit.log("report.generated", { period: "2025-01", items: 240 })
    • 可配置落盘或外部集中采集(需显式权限)

2.7 FFI桥接:Python/R 集成

  • Python
    • foreign python "mymath" { fn sma(data: [Decimal], window: Int) -> [Decimal] }
    • 支持虚拟环境隔离与白名单模块
  • R
    • foreign r "stats" { fn median(xs: [Decimal]) -> Decimal }
  • 数据拷贝
    • 零拷贝传参针对基本向量/标量;复杂结构序列化为Arrow/JSON(可控)

2.8 大规模报表生成与模板管理

  • 模板引擎 Slate
    • 模板变量与区块:{{ title }},{{#each items}}{{/each}}
    • 主题与片段复用:include "partials/header.slt"
  • 流式生成
    • report.stream(template, iterator, out: sink) 降低峰值内存
  • 输出格式
    • render_pdf, render_html;PDF 渲染内置分页与目录
  • 模板版本
    • 在 manifest 中固定模板包版本,避免部署时样式漂移

2.9 部署、版本策略与回滚

  • 构建与打包
    • lgs build -O2 -o app.lgx main.ls
    • lgs pack --with plugins/ --templates/ 生成制品
  • 版本与通道
    • semver:主版本破坏性变更,次版本向后兼容新增,补丁为修复
    • 通道:dev/staging/prod;支持金丝雀部署 lgs deploy --channel staging
  • 配置与迁移
    • 环境配置分离(不含密钥);变更需可回滚的迁移脚本
  • 回滚
    • lgs rollback --to v1.2.3 自动恢复上一稳定版本与缓存标签

  1. 示例教程(含可运行代码)

说明

  • 所有示例均可在无网络、无文件权限的沙箱中运行。
  • 如需写文件,示例内会显式请求权限;否则仅打印到控制台或内存缓冲。

3.1 入门:从CSV字符串导入、分类与预算汇总 使用场景

  • 将简化的交易CSV载入内存,按分类聚合并输出月度预算对比。

代码(beginner_level.ls)

// 教程1:入门 —— CSV导入、分类与预算汇总(内存示例)

import std.csv
import std.time
import std.money
import std.collections
import report.slate as slate

type Tx = {
  id: String,
  date: Date,
  payee: String,
  amount: Money,
  category: String?,
  account_id: String,
  tags: [String]
}

fn parse_tx(row: Map[String, String]) -> Tx {
  let amt = Decimal.parse(row["amount"])
  let ccy = row.get("currency").unwrap_or("USD")
  Tx {
    id: row["id"],
    date: date(row["date"]),
    payee: row["payee"],
    amount: Money(ccy, amt),
    category: row.get("category"),
    account_id: row.get("account_id").unwrap_or("acc-local"),
    tags: row.get("tags").map(t => t.split("|")).unwrap_or([])
  }
}

fn main() {
  // 模拟CSV输入
  const csv_data = "id,date,payee,amount,currency,category\n" +
                   "t1,2025-01-03,Grocery,-45.60,USD,Food\n" +
                   "t2,2025-01-05,Salary,3000.00,USD,Income\n" +
                   "t3,2025-01-10,Rent,-1200.00,USD,Housing\n" +
                   "t4,2025-01-12,Cafe,-6.50,USD,Food\n" +
                   "t5,2025-01-15,Transport,-30.00,USD,Transit\n";

  let rows = csv.read_string(csv_data, header: true);
  let txs: [Tx] = rows.map(parse_tx);

  // 简单预算(预计开销)
  let budget = {
    "Food": 200.00:USD,
    "Housing": 1200.00:USD,
    "Transit": 100.00:USD
  };

  // 过滤支出(负数),按分类求和
  let spends = txs
    .filter(t => t.amount < 0.0:USD)
    .group_by(t => t.category.unwrap_or("Uncategorized"))
    .map((cat, group) => {
      let total = group.sum(g => g.amount).abs();
      { category: cat, spent: total, budget: budget.get(cat).unwrap_or(0.0:USD) }
    })
    .order_by(x => x.category);

  // 控制台输出
  println("分类支出与预算对比:");
  for item in spends {
    let diff = item.budget - item.spent;
    println("- {cat}: 花费 {spent}, 预算 {budget}, 结余 {diff}",
      cat=item.category, spent=item.spent, budget=item.budget, diff=diff);
  }

  // 生成简单HTML(内存)
  let tpl = "<h1>{{ title }}</h1>{{#each items}}<div>{{category}}: {{spent}} / {{budget}}</div>{{/each}}";
  let doc = slate.render_string(tpl, { title: "2025-01 预算", items: spends });
  // 仅展示前100字符
  println("HTML预览: {s}...", s=doc.substring(0, 100));
}

运行结果说明

  • 控制台打印分类支出与预算结余。
  • 生成的HTML示例在内存中渲染并截断展示,避免写文件权限。

3.2 并发与任务队列:多账户流水聚合与月报PDF 使用场景

  • 模拟两个账户的拉取操作并行运行,将结果汇总后生成PDF月报(如无文件权限,则展示字节长度)。

代码(concurrency_report.ls)

// 教程2:并发与任务队列 —— 并行拉取与PDF报表(纯本地模拟)

import std.time
import std.money
import std.collections
import report.slate as slate
import report.output as output  // 提供内存/文件写出
import std.concurrent

type Tx = { id: String, date: Date, payee: String, amount: Money, category: String?, account_id: String, tags: [String] }

async fn fetch_account_mock(account_id: String) -> [Tx] {
  // 模拟I/O延时
  sleep(150ms);
  if account_id == "A" {
    return [
      Tx { id: "a1", date: date("2025-01-02"), payee: "Grocery", amount: -23.10:USD, category: "Food", account_id: "A", tags: [] },
      Tx { id: "a2", date: date("2025-01-09"), payee: "Salary",  amount: 2000.00:USD, category: "Income", account_id: "A", tags: [] }
    ];
  } else {
    return [
      Tx { id: "b1", date: date("2025-01-05"), payee: "Rent",    amount: -900.00:USD, category: "Housing", account_id: "B", tags: [] },
      Tx { id: "b2", date: date("2025-01-15"), payee: "Cafe",    amount: -6.80:USD,  category: "Food",    account_id: "B", tags: [] }
    ];
  }
}

fn month_summary(txs: [Tx]) -> Map[String, Any] {
  let period = "2025-01";
  let income = txs.filter(t => t.amount > 0.0:USD).sum(t => t.amount);
  let expense = txs.filter(t => t.amount < 0.0:USD).sum(t => t.amount).abs();
  let by_cat = txs
    .filter(t => t.amount < 0.0:USD)
    .group_by(t => t.category.unwrap_or("Uncategorized"))
    .map((k, g) => { category: k, spent: g.sum(x => x.amount).abs() })
    .order_by(x => -x.spent);
  { period: period, income: income, expense: expense, net: income - expense, categories: by_cat }
}

fn main() {
  // 1) 并发拉取
  let accounts = ["A", "B"];
  let tasks = accounts.map(a => spawn fetch_account_mock(a));
  let parts: [[Tx]] = await all(tasks);
  let txs = parts.flatten();

  // 2) 缓存示例:按月份缓存汇总(TTL 1小时)
  let summary = cache(key: "summary:2025-01", ttl: 1h) { month_summary(txs) };

  // 3) 生成PDF(内存)
  let tpl = """
  <h1>月度报表 {{period}}</h1>
  <div>收入:{{income}} 支出:{{expense}} 结余:{{net}}</div>
  <h2>分类</h2>
  {{#each categories}}<div>{{category}}: {{spent}}</div>{{/each}}
  """;
  let html = slate.render_string(tpl, summary);
  let pdf_bytes = output.render_pdf_from_html(html);

  // 4) 尝试写文件(需要权限);否则打印字节大小
  match request_permission("files.write", "./out/") {
    Ok(_) => {
      output.write_file("./out/report-2025-01.pdf", pdf_bytes);
      println("PDF已写入 ./out/report-2025-01.pdf");
    }
    Err(_) => {
      println("PDF字节长度(未写文件):{n}", n=pdf_bytes.len());
    }
  }
}

运行结果说明

  • 所有账户的流水在150ms延时下并发聚合,总耗时接近单账户耗时。
  • 若授予写权限,输出PDF文件;否则打印生成的字节长度。

3.3 插件开发:账户接入(Mock Connector) 使用场景

  • 实现一个只读的本地账户连接器插件,提供账户列表与交易拉取。

代码(plugin_connector.ls)

// 教程3:插件 —— 账户接入(Mock版,无外部网络)

import plugin.api.account as account
import std.time
import std.money
import std.uuid

type Tx = { id: String, date: Date, payee: String, amount: Money, category: String?, account_id: String, tags: [String] }

struct MockCtx { seed: Int }

struct MockConnector {}

impl account.AccountConnector for MockConnector {
  fn id() -> String { "mock.local" }

  fn list_accounts(ctx: account.ConnectorContext) -> [account.Account] {
    return [
      account.Account { id: "mock-001", name: "Mock Checking", currency: "USD" },
      account.Account { id: "mock-002", name: "Mock Savings",  currency: "USD" }
    ];
  }

  fn fetch_transactions(ctx: account.ConnectorContext, account_id: String, range: account.DateRange) -> [account.Transaction] {
    // 在本地生成确定性数据,不进行任何外部访问
    let days = 5;
    let mut out: [account.Transaction] = [];
    for i in 0..days {
      let d = range.start.plus_days(i);
      if d > range.end { break; }
      let t = account.Transaction {
        id: uuid.v4(),
        date: d,
        payee: if i % 2 == 0 { "Local Grocery" } else { "Local Cafe" },
        amount: if i % 2 == 0 { -12.34:USD } else { -4.56:USD },
        category: Some("Food"),
        account_id: account_id,
        tags: []
      };
      out.push(t);
    }
    return out;
  }
}

fn main() {
  account.register_connector(MockConnector {});
  let ctx = account.ConnectorContext { /* 无敏感配置 */ };

  let accts = account.list("mock.local", ctx);
  println("已注册账户数:{n}", n=accts.len());

  let range = account.DateRange { start: date("2025-01-01"), end: date("2025-01-10") };
  let txs = account.fetch("mock.local", ctx, accts[0].id, range);

  // 审计记录
  audit.log("connector.fetch", { connector: "mock.local", account: accts[0].id, count: txs.len() });

  println("示例交易:{p} {a}", p=txs[0].payee, a=txs[0].amount);
}

运行结果说明

  • 无网络访问,仅生成确定性数据。
  • 通过 audit.log 记录关键操作,满足可追踪要求。

3.4 性能与剖析:大数据聚合与热点定位 使用场景

  • 生成10万条模拟交易,使用剖析器定位热点并通过arena与缓存优化。

代码(profiling_perf.ls)

// 教程4:性能 —— 大规模聚合与剖析

import std.time
import std.money
import std.collections

type Tx = { id: String, date: Date, payee: String, amount: Money, category: String?, account_id: String, tags: [String] }

fn gen(n: Int) -> [Tx] {
  with arena {
    let mut xs: [Tx] = [];
    for i in 0..n {
      xs.push(Tx {
        id: "t" + i.to_string(),
        date: date("2025-01-01").plus_days(i % 28),
        payee: "Store " + (i % 100).to_string(),
        amount: if i % 10 == 0 { 100.00:USD } else { - (i % 20 + 1).to_decimal():USD },
        category: Some(if i % 3 == 0 { "Food" } else { "Other" }),
        account_id: "acc-" + (i % 5).to_string(),
        tags: []
      });
    }
    return xs; // arena在块末释放临时分配
  }
}

@profile
fn agg_month(txs: [Tx]) -> Map[String, Money] {
  // 缓存每个商户的开销(TTL 5分钟)
  let by_payee = cache("agg:payee:2025-01", 5m) {
    txs.filter(t => t.amount < 0.0:USD)
       .group_by(t => t.payee)
       .map((k, g) => (k, g.sum(x => x.amount).abs()))
       .to_map()
  };
  // 再次聚合:top-5商户
  let mut top5: [(String, Money)] = by_payee.to_list()
    .order_by(p => -p.1)
    .take(5);
  return top5.to_map();
}

fn main() {
  let txs = gen(100_000);
  let top = agg_month(txs);
  println("Top商户数:{n}", n=top.len());
}

剖析使用

  • 命令:lgs profile run profiling_perf.ls
  • 输出:CPU火焰图、内存采样、缓存命中率;根据报告优化数据结构或缓存粒度。

3.5 FFI:Python/R 统计与图表 使用场景

  • 调用Python计算简单移动平均(SMA),调用R计算中位数,在报表中展示。

代码(ffi_stats.ls)

// 教程5:FFI —— Python与R 统计集成(仅白名单模块)

import report.slate as slate
import report.output as output

// 在 manifest 中需声明:ffi.python: ["mymath"], ffi.r: ["stats"]
foreign python "mymath" {
  fn sma(data: [Decimal], window: Int) -> [Decimal]
}
foreign r "stats" {
  fn median(xs: [Decimal]) -> Decimal
}

fn main() {
  let xs = [1.0, 2.0, 3.0, 6.0, 10.0];
  let s = sma(xs, 3);     // Python
  let m = median(xs);     // R

  let tpl = "<h1>统计</h1><div>SMA(3):{{s}}</div><div>Median:{{m}}</div>";
  let html = slate.render_string(tpl, { s: s, m: m });
  let pdf = output.render_pdf_from_html(html);

  println("PDF字节长度:{n}", n=pdf.len());
}

运行结果说明

  • 在沙箱启用的前提下,调用白名单中的FFI函数并渲染结果。
  • 未授予写权限时,仅输出字节长度。

3.6 部署与回滚:从构建到稳定发布 使用场景

  • 构建可发布制品,灰度到staging,验证后发布prod,提供一键回滚。

示例流程(命令行)

  • lgs build -O2 -g -o app.lgx main.ls
  • lgs pack --with plugins/ --templates/ -o release.tgz
  • lgs deploy --channel staging --artifact release.tgz
  • lgs health --channel staging
  • lgs promote --from staging --to prod
  • 回滚:lgs rollback --to v1.4.2

预期结果

  • 各通道按版本独立运行,模板与插件版本锁定,必要时快速回退到已验证版本。

  1. 最佳实践
  • 货币与精度
    • 使用 Money 类型进行所有金额计算,避免 Decimal 与 Money 混用。
    • 跨币种转换使用 fx.convert(amount, to: "USD", date),不要手写汇率。
  • 时间与时区
    • 统一使用UTC存储,展现时格式化到本地时区。
    • 报表期统一按闭区间 [start, end] 明确边界。
  • 数据导入与幂等
    • 以交易外部ID+来源(account_id)作为幂等键,避免重复入账。
    • 导入前后记录 audit.log,标注批次号与计数。
  • 并发与任务队列
    • IO密集型作业使用 queue(concurrency: N) 提升吞吐;计算密集型控制并发防止过载。
    • 为每个任务附带去重键与超时,失败使用指数退避重试。
  • 缓存层次
    • 原始数据缓存(短TTL)+ 聚合结果缓存(中TTL)+ 模板渲染缓存(按版本/参数tag)。
    • 重要缓存使用标签化失效,避免陈旧数据泄露。
  • 模板与资源
    • 模板包与版本固定,配套静态资源哈希命名;变更需审阅与回归。
  • 安全与合规
    • 严格最小权限:仅授予需要的 files.* 与 ffi.*。
    • 定期审阅审计日志与权限变更,设置合理的保留期与加固策略。
  • 错误处理
    • 使用 Result 显式处理I/O与FFI错误;在对账关键路径中 fail-fast 并记录审计。
  • 配置与密钥
    • 将密钥注入到受管密钥服务,不在代码与仓库中硬编码;读取前显式申请权限。
  • 部署策略
    • 使用 staging 金丝雀试验,按指标(错误率、延迟、资源占用)自动/手动晋级;保留最近N个版本以做快速回滚。

  1. 附录(快速参考与资源)

5.1 语法速查

  • 注释
    • // 行注释;/* 块注释 */
  • 字面量
    • 日期:date("YYYY-MM-DD")
    • 金额:123.45:USD 或 Money("USD", 123.45)
  • 控制流
    • if/else, match, for/while
  • 函数与异步
    • fn f(a: T) -> U { ... }
    • async fn g(...) -> R { ... }; let t = spawn g(...); await t
  • 集合操作
    • filter/map/reduce/group_by/order_by/take/flatten
    • 管道:xs |> f |> g
  • 错误
    • Result[T,E];try {...} except e { ... };throw err

5.2 标准库常用函数

  • std.money
    • abs(m: Money) -> Money;format(m) -> String
    • fx.convert(m: Money, to: String, date: Date?) -> Money
  • std.time
    • date(str) -> Date;month(Date) -> Int;plus_days(Int) -> Date
  • std.collections
    • group_by, sum, to_map, to_list, order_by
  • report.slate
    • render_string(tpl: String, data: Any) -> String
  • report.output
    • render_pdf_from_html(html: String) -> Bytes
    • write_file(path: String, bytes: Bytes) -> Unit
  • std.concurrent
    • queue(name: String, concurrency: Int)
    • spawn(task) -> Task;await Task;await all([Task])
    • timeout(d: Duration);retry(policy, max: Int)

5.3 插件与安全

  • 插件接口
    • AccountConnector: id, list_accounts, fetch_transactions
    • ReportBlock: name, render
  • 权限键
    • files.read / files.write / ffi.python / ffi.r
    • audit.write(若外部落盘或集中采集)
  • 审计事件建议
    • connector.registered / connector.fetch / report.generated / cache.invalidate

5.4 CLI 常用命令

  • 运行与构建
    • lgs run script.ls
    • lgs build -O2 -o app.lgx script.ls
  • 剖析
    • lgs profile run script.ls
  • 打包与部署
    • lgs pack --with plugins/ --templates/ -o release.tgz
    • lgs deploy --channel staging --artifact release.tgz
    • lgs promote --from staging --to prod
    • lgs rollback --to vX.Y.Z

5.5 常见错误与排查

  • 缺少权限
    • 症状:运行时报 “permission denied: files.write”
    • 解决:在 manifest 中显式声明权限,或使用 request_permission
  • 货币混算
    • 症状:USD 与 EUR 直接相加报类型错误
    • 解决:先使用 fx.convert 统一币种
  • FFI 模块未授权
    • 症状:调用 Python/R 报 “ffi module not allowed”
    • 解决:添加 ffi.python/ffi.r 白名单并重新打包部署

5.6 资源链接

版权与免责声明

  • 本文档旨在帮助开发者学习与使用 LedgerScript,不构成任何形式的财务或投资建议。
  • 示例仅用于技术演示,切勿用于真实生产环境中的敏感数据处理,除非经过完整的安全与合规评审。

示例详情

解决的问题

将个人理财编程语言的“复杂说明”转化为“可直接使用的高质量内容”,帮助团队在发布前后快速产出结构清晰的使用文档与分级教程;以真实可运行的示例降低学习门槛,缩短新人上手时间;通过统一风格与多场景适配(官网、社区、课程、内部培训),提升用户理解力与信任感,驱动试用转化与长期留存;同时减少重复答疑与维护成本,让产品更易传播、更易购买。

适用用户

个人理财编程语言作者

发布前快速产出标准化使用文档、升级说明与示例合集,覆盖语法变化与迁移指引,减少发布后重复答疑。

技术文档负责人与开发经理

为团队搭建统一知识库结构,一键生成模块页面与导航,制定最佳实践规范,缩短新人上手与评审周期。

教学讲师与培训机构

按课时自动生成分层教程与可运行练习,附步骤与结果说明,快速备课并提升课堂实操与作业完成率。

特征总结

一键生成完整语言文档,覆盖语法概览、实操场景与上手路径,快速缩短从学习到应用的时间。
自动产出可直接运行的示例代码,配步骤与预期结果说明,降低试错成本,确保立即可用。
按业务场景组织内容,如预算、记账、投资追踪与分析,便于团队按需查找并复用。
内置从入门到进阶的分级教程,逐章解锁关键能力,支持自学与团队培训同步推进。
多格式一键适配,轻松导出为网站页面、知识库文章或PDF手册,省去繁琐排版。
针对功能列表自动梳理语法要点与使用边界,生成清晰目录与导航,显著提升可读性。
智能文案润色与术语简化,面向非专业读者友好呈现,减少沟通成本与学习压力。
内置最佳实践与常见误区提醒,规范团队写法,持续提升文档质量与可维护性。
可按目标用户群与复杂度调节讲解深度,提供差异化版本,满足多层次学习需求。
全流程规范校验与安全审查,过滤敏感信息与不当建议,保障发布风险可控。

如何使用购买的提示词模板

1. 直接在外部 Chat 应用中使用

将模板生成的提示词复制粘贴到您常用的 Chat 应用(如 ChatGPT、Claude 等),即可直接对话使用,无需额外开发。适合个人快速体验和轻量使用场景。

2. 发布为 API 接口调用

把提示词模板转化为 API,您的程序可任意修改模板参数,通过接口直接调用,轻松实现自动化与批量处理。适合开发者集成与业务系统嵌入。

3. 在 MCP Client 中配置使用

在 MCP client 中配置对应的 server 地址,让您的 AI 应用自动调用提示词模板。适合高级用户和团队协作,让提示词在不同 AI 工具间无缝衔接。

AI 提示词价格
¥15.00元
先用后买,用好了再付款,超安全!

您购买后可以获得什么

获得完整提示词模板
- 共 607 tokens
- 4 个可调节参数
{ 功能列表 } { 文档格式 } { 目标用户群体 } { 语言复杂度级别 }
获得社区贡献内容的使用权
- 精选社区优质案例,助您快速上手提示词
限时免费

不要错过!

免费获取高级提示词-优惠即将到期

17
:
23
小时
:
59
分钟
:
59