"""重叠更新、已收盘条封存与未完成条隔离;无网络或调度。""" import copy import json sessions = ["2026-10-19", "2026-10-20", "2026-10-21", "2026-10-22", "2026-10-23"] stored = {day: {"close": close, "volume": 100, "complete": True} for day, close in zip(sessions[:3], [10, 11, 12])} incoming = [(sessions[1], {"close": 11, "volume": 100, "complete": True}), (sessions[2], {"close": 12.5, "volume": 100, "complete": True}), (sessions[3], {"close": 13, "volume": 100, "complete": True}), (sessions[4], {"close": 13.2, "volume": 70, "complete": False})] overlap_start = sessions[sessions.index(max(stored))-1] def merge(old, response): if len({d for d, _ in response}) != len(response): raise ValueError("duplicate_response_date") result, provisional, log = copy.deepcopy(old), {}, {"added": [], "revised": [], "unchanged": []} for day, row in response: if type(row["complete"]) is not bool: raise ValueError("invalid_completion_flag") if day < overlap_start or day not in sessions: raise ValueError("outside_request") if not row["complete"]: provisional[day] = dict(row) continue if day not in result: log["added"].append(day) elif row != result[day]: log["revised"].append({"date": day, "before": result[day], "after": row}) else: log["unchanged"].append(day) result[day] = dict(row) return result, provisional, log updated, provisional, first = merge(stored, incoming) again, provisional_again, second = merge(updated, incoming) assert overlap_start == "2026-10-20" and len(updated) == 4 assert first["added"] == ["2026-10-22"] and first["revised"][0]["date"] == "2026-10-21" assert stored["2026-10-21"]["close"] == 12 and updated["2026-10-21"]["close"] == 12.5 assert again == updated and second["added"] == second["revised"] == [] assert provisional == provisional_again and "2026-10-23" not in updated try: merge(stored, incoming + [incoming[0]]) except ValueError as exc: assert str(exc) == "duplicate_response_date" else: raise AssertionError("重复响应日期必须阻断") print(json.dumps({"overlap_start": overlap_start, "first": first, "sealed_rows": len(updated), "provisional_dates": sorted(provisional), "second_added": second["added"], "second_revised": second["revised"]}, sort_keys=True))