4. 资金日终头寸计算

任务说明

给定银行账户的日初余额和当日交易流水,计算每个账户的日终头寸(日初余额 + 当日净流水),汇总集团整体头寸,并标记日终余额为负的透支账户。

数据结构与计算流程

日初余额表 account, open_bal 交易流水表 account, amount 按账户聚合净流水 sum(amount) 日终头寸 open_bal + net 透支标记 close_bal < 0

完整实现

from collections import defaultdict

# 日初余额:账户 -> 日初余额
open_balances = {
    "ACC001": 500000.00,
    "ACC002": 120000.00,
    "ACC003": 80000.00,
    "ACC004": 30000.00,
}

# 当日交易流水:每笔为 (账户, 金额),正为收入,负为支出
transactions = [
    ("ACC001", -200000.00),
    ("ACC001", 150000.00),
    ("ACC002", -180000.00),
    ("ACC002", 30000.00),
    ("ACC003", -50000.00),
    ("ACC003", -40000.00),
    ("ACC004", -35000.00),
    ("ACC004", 2000.00),
]

def compute_eod_positions(open_bal: dict, txs: list) -> list:
    """计算每个账户的日终头寸并标记透支。"""
    net_flow = defaultdict(float)
    for acct, amt in txs:
        net_flow[acct] += amt

    results = []
    for acct, ob in open_bal.items():
        net = net_flow.get(acct, 0.0)
        close = ob + net
        results.append({
            "account": acct,
            "open_balance": round(ob, 2),
            "net_flow": round(net, 2),
            "close_balance": round(close, 2),
            "overdraft": close < 0,
        })
    return results

def group_total(results: list) -> dict:
    """汇总集团整体头寸。"""
    total_open = sum(r["open_balance"] for r in results)
    total_net = sum(r["net_flow"] for r in results)
    total_close = sum(r["close_balance"] for r in results)
    overdrafts = [r["account"] for r in results if r["overdraft"]]
    return {
        "total_open": round(total_open, 2),
        "total_net_flow": round(total_net, 2),
        "total_close": round(total_close, 2),
        "overdraft_accounts": overdrafts,
    }

if __name__ == "__main__":
    positions = compute_eod_positions(open_balances, transactions)
    print(f"{'账户':<8}{'日初余额':>12}{'净流水':>12}{'日终头寸':>12}{'透支':>6}")
    for r in positions:
        flag = "是" if r["overdraft"] else "否"
        print(f"{r['account']:<8}{r['open_balance']:>12.2f}{r['net_flow']:>12.2f}{r['close_balance']:>12.2f}{flag:>6}")

    total = group_total(positions)
    print("\n集团汇总:")
    print(f"  日初总余额: {total['total_open']:.2f}")
    print(f"  当日净流水: {total['total_net_flow']:.2f}")
    print(f"  日终总头寸: {total['total_close']:.2f}")
    print(f"  透支账户: {total['overdraft_accounts'] or '无'}")

运行方式

python eod_position.py

验证方法与通过条件

  • 逐账户核对:日终头寸 = 日初余额 + 该账户所有交易金额之和。例如 ACC002 日初 120000,净流水 -150000,日终 -30000,应标记为透支。
  • 集团汇总:日终总头寸应等于各账户日终头寸之和,也等于日初总余额加当日净流水总额。
  • 透支账户列表应包含所有日终余额为负的账户,本例中为 ACC002 和 ACC004。
  • 若输出中每个账户的 close_balance 与手工核算一致,且透支标记正确,则通过。