自建策略每日运行日志自动存档程序,留存每一日策略运行参数与操作记录。
策略每日运行日志自动存档程序留存策略参数与操作记录教学级量化交易原型内容包含免责声明和风险提示不荐股、不自动化交易、不引导开户、无任何引流。一、实际应用场景描述在智能证券投资课程中策略运行日志Strategy Run Log与可复现性Reproducibility是量化交易系统开发的核心教学内容。本程序适用于- 高校量化投资、算法交易课程实验- 个人量化策略开发与调试- 策略运行审计与归因分析教学- 多策略并行管理的日志系统演示核心目标- 每日自动记录策略运行参数- 留存当日操作记录信号、下单、持仓变更- 结构化存档便于后续复盘与审计- 强调本地存储、用户自主管理✅ 不连接券商系统✅ 不执行真实交易✅ 仅作为策略日志管理教学工具二、痛点引入真实可感知痛点 表现那天为啥买忘了 缺乏操作记录复盘无据可查参数漂移 今天改了参数明天不记得了无法复现 历史回测和实盘差异无法定位多策略混乱 同时跑 3 个策略日志混在一起工具过重 专业日志系统ELK 等对个人过重 需要一个轻量、本地、可解释、可复现的策略日志工具三、核心逻辑讲解工程视角1️⃣ 数据模型设计StrategyRunLog├── run_id 运行唯一 IDUUID├── date 运行日期├── strategy_name 策略名称├── parameters 策略参数快照JSON├── signals 当日产生的信号列表├── orders 当日操作记录列表└── notes 备注如 市场异常、临时调整2️⃣ 日志内容设计教学用模块 记录内容策略参数 均线周期、RSI 阈值、仓位上限等市场快照 当日行情概要开盘 / 收盘 / 波动率信号记录 买入 / 卖出 / 观望 触发条件操作记录 下单方向、数量、价格模拟异常标记 数据缺失、信号冲突等3️⃣ 存档流程策略每日运行结束↓收集参数 信号 操作↓生成唯一 run_id↓序列化为 JSON↓按日期目录存储4️⃣ 目录结构设计strategy_logs/├── 2025-07-14/│ ├── run_1a2b3c.json│ └── run_4d5e6f.json├── 2025-07-15/│ └── run_7g8h9i.json└── index.json # 总索引5️⃣ 设计原则- 只记录不执行- 参数快照化确保可复现- 每日独立存档便于审计四、Python 模块化代码可直接运行 项目结构strategy_logger/│├── main.py├── models.py├── logger.py├── serializer.py├── reporter.py├── storage.py├── README.md└── DISCLAIMER.md✅ models.py数据建模models.py策略运行日志数据模型import uuidimport jsonfrom datetime import datetimeclass StrategyRunLog:单次策略运行日志def __init__(self,strategy_name,parameters,market_snapshot,signalsNone,ordersNone,notes):strategy_name: 策略名称parameters: 策略参数字典market_snapshot: 市场快照字典signals: 信号列表orders: 操作记录列表notes: 备注self.run_id str(uuid.uuid4())self.date datetime.now().strftime(%Y-%m-%d)self.timestamp datetime.now().isoformat()self.strategy_name strategy_nameself.parameters parametersself.market_snapshot market_snapshotself.signals signals or []self.orders orders or []self.notes notesdef to_dict(self):序列化为字典return {run_id: self.run_id,date: self.date,timestamp: self.timestamp,strategy_name: self.strategy_name,parameters: self.parameters,market_snapshot: self.market_snapshot,signals: self.signals,orders: self.orders,notes: self.notes}classmethoddef from_dict(cls, data):从字典还原log cls(data[strategy_name],data[parameters],data[market_snapshot],data[signals],data[orders],data[notes])log.run_id data[run_id]log.date data[date]log.timestamp data[timestamp]return log✅ logger.py核心日志引擎logger.py策略运行日志引擎import osimport jsonfrom datetime import datetimefrom models import StrategyRunLogclass StrategyLogger:策略日志管理器def __init__(self, base_dirstrategy_logs):self.base_dir base_diros.makedirs(base_dir, exist_okTrue)self.index_path os.path.join(base_dir, index.json)self._load_index()def _load_index(self):加载总索引if os.path.exists(self.index_path):with open(self.index_path, r) as f:self.index json.load(f)else:self.index {total_runs: 0, runs: []}def _save_index(self):保存总索引with open(self.index_path, w) as f:json.dump(self.index, f, ensure_asciiFalse, indent2)def log_run(self, run_log):核心方法存档一次策略运行记录# 按日期创建子目录date_dir os.path.join(self.base_dir, run_log.date)os.makedirs(date_dir, exist_okTrue)# 写入当日运行记录filename frun_{run_log.run_id[:8]}.jsonfilepath os.path.join(date_dir, filename)with open(filepath, w) as f:json.dump(run_log.to_dict(), f, ensure_asciiFalse, indent2)# 更新总索引self.index[total_runs] 1self.index[runs].append({run_id: run_log.run_id,date: run_log.date,strategy: run_log.strategy_name,file: os.path.join(run_log.date, filename),signal_count: len(run_log.signals),order_count: len(run_log.orders)})self._save_index()return filepathdef get_run(self, run_id):按 run_id 检索for entry in self.index[runs]:if entry[run_id] run_id:filepath entry[file]with open(os.path.join(self.base_dir, filepath), r) as f:return StrategyRunLog.from_dict(json.load(f))return Nonedef list_runs(self, dateNone, strategy_nameNone):列出所有运行记录可选过滤results self.index[runs]if date:results [r for r in results if r[date] date]if strategy_name:results [r for r in results if r[strategy] strategy_name]return results✅ serializer.py参数快照工具serializer.py策略参数快照与对比工具def snapshot_parameters(params_dict):将策略参数固化为可复现的快照import jsonreturn json.dumps(params_dict, sort_keysTrue, ensure_asciiFalse)def compare_parameters(snap_a, snap_b):对比两次运行的参数差异import jsona json.loads(snap_a)b json.loads(snap_b)diffs {}all_keys set(list(a.keys()) list(b.keys()))for k in all_keys:if a.get(k) ! b.get(k):diffs[k] {old: a.get(k), new: b.get(k)}return diffs✅ reporter.py日志报告输出reporter.py策略运行日志报告def report_run(run_log):打印单次运行日志print(\n * 65)print(f【策略运行日志】)print( * 65)print(f Run ID{run_log.run_id})print(f 策略{run_log.strategy_name})print(f 日期{run_log.date})print(f 时间{run_log.timestamp})print(f\n 策略参数快照)print(- * 65)for k, v in run_log.parameters.items():print(f {k} {v})print(f\n 市场快照)print(- * 65)for k, v in run_log.market_snapshot.items():print(f {k} {v})if run_log.signals:print(f\n 信号记录{len(run_log.signals)} 条)print(- * 65)for i, sig in enumerate(run_log.signals, 1):print(f {i}. [{sig.get(time, N/A)}] {sig.get(type, )})print(f 条件{sig.get(condition, )})print(f 结果{sig.get(result, )})if run_log.orders:print(f\n 操作记录{len(run_log.orders)} 条)print(- * 65)for i, order in enumerate(run_log.orders, 1):print(f {i}. {order.get(action, )} | f数量{order.get(qty, )} | f价格{order.get(price, )})if run_log.notes:print(f\n 备注{run_log.notes})print( * 65)def report_index(logger):打印总索引print(f\n 日志总览共 {logger.index[total_runs]} 次运行)print(- * 65)for r in logger.index[runs]:print(f {r[date]} | {r[strategy]} | f信号 {r[signal_count]} 条 | f操作 {r[order_count]} 条)✅ storage.py本地存储——兼容性封装storage.py兼容性封装委托给 logger 模块from logger import StrategyLogger# 暴露给 main.py 使用__all__ [StrategyLogger]✅ main.py交互入口main.py策略每日运行日志自动存档工具from datetime import datetimefrom models import StrategyRunLogfrom logger import StrategyLoggerfrom serializer import snapshot_parametersfrom reporter import report_run, report_indexdef main():print( 策略运行日志自动存档工具教学版)print(留存每一日策略运行参数与操作记录\n)logger StrategyLogger()while True:print(f\n 选择操作)print( 1. 存档今日策略运行)print( 2. 查看运行记录列表)print( 3. 查看某次运行详情)print( 4. 退出)choice input(\n请选择1/2/3/4)if choice 1:# 存档strategy_name input(策略名称)print(\n 策略参数JSON 格式空行结束)print(示例ma_short: 5)params {}while True:line input()if not line:breakk, v line.split(:, 1)# 尝试转为数字v v.strip()try:v float(v) if . in v else int(v)except ValueError:passparams[k.strip()] vprint(\n 市场快照JSON 格式空行结束)print(示例close: 3250.8)market {}while True:line input()if not line:breakk, v line.split(:, 1)v v.strip()try:v float(v) if . in v else int(v)except ValueError:passmarket[k.strip()] v# 信号录入signals []print(\n 录入信号空行结束)while True:t input(信号类型如 BUY/SSELL/HOLD空结束)if not t:breakcond input(触发条件)res input(信号结果)time_str input(触发时间HH:MM可选) or N/Asignals.append({type: t,condition: cond,result: res,time: time_str})# 操作录入orders []print(\n 录入操作空行结束)while True:act input(操作BUY/SELL空结束)if not act:breakqty int(input(数量))price float(input(价格))orders.append({action: act,qty: qty,price: price})notes input(\n 备注可选)# 创建日志run_log StrategyRunLog(strategy_name, params, market, signals, orders, notes)# 存档filepath logger.log_run(run_log)print(f\n✅ 日志已存档{filepath})print(f Run ID{run_log.run_id})elif choice 2:report_index(logger)elif choice 3:run_id input(输入 Run ID完整或前 8 位)# 模糊匹配matched Nonefor r in logger.index[runs]:if r[run_id].startswith(run_id):matched logger.get_run(r[run_id])breakif matched:report_run(matched)else:print(⚠️ 未找到对应 Run ID)elif choice 4:print(\n 再见日志已安全存档。)breakelse:print(⚠️ 无效选择)if __name__ __main__:main()五、README 与使用说明# 策略每日运行日志自动存档工具教学版## 项目说明留存每一日策略运行参数与操作记录便于复盘与审计。## 使用方式bashpython main.py## 操作流程### 存档运行记录选择操作1策略名称均线突破策略ma_short: 5ma_long: 20rsi_threshold: 30空行结束close: 3250.8volume: 185000000volatility: 1.8空行结束信号类型BUY触发条件MA5 MA20 and RSI 30信号结果生成买入信号触发时间09:45空行结束可录多条操作BUY数量100价格3248.5空行结束可录多条## 存储结构strategy_logs/├── 2025-07-14/│ └── run_1a2b3c4d.json└── index.json## 适用范围- 量化投资策略课程- 策略开发与调试- 运行审计与归因分析## 注意事项- 不执行真实交易- 不连接券商系统- 使用前请阅读 DISCLAIMER.md六、DISCLAIMER.md免责声明与风险提示# 免责声明与风险提示## 免责声明本程序仅供**教学与科研用途**用于演示策略运行日志的归档方法。作者不提供任何投资建议不推荐任何策略不承诺任何收益。## 风险提示1. 日志完整性依赖程序正常退出异常中断可能丢失当日记录2. JSON 存储不适合高频策略每秒数百条信号此类场景应使用时序数据库3. Run ID 为随机 UUID不支持自定义命名查找需借助索引4. 参数快照仅记录提交时的状态运行时动态修改不会被捕获5. 日志文件未加密多用户环境需注意权限控制使用本工具产生的任何后果作者概不负责。七、核心知识点卡片教学向分类 内容Python 类、UUID、JSON 序列化、文件系统操作量化交易 策略可复现性、参数快照、运行审计系统工程 日志分层设计、索引管理、按日分区数据分析 历史回放、参数漂移检测工程思想 模块化、可扩展、可审计可扩展性 可接入数据库、支持多策略并行写入八、总结工程师视角这是一个完全中立、去营销化、可教学的原型系统✅ 不鼓吹任何策略✅ 不伪装成日志平台✅ 不替代专业运维工具它真正展示的是如何用 Python 把今天策略怎么跑的从模糊记忆变成可检索、可复现、可审计的结构化资产核心教学价值传统做法 日志化后参数好像改过 每日快照精确对比为什么今天信号不一样 参数 市场快照 → 可回放当时为什么买 信号记录 触发条件 完整归因策略失效了 逐日对比参数漂移定位退化点日志是量化交易者的黑匣子——没它你飞了一万小时连自己怎么飞的都不知道。本文代码仅供学习和技术交流不构成任何投资建议股市有风险入市需谨慎利用AI解决实际问题如果你觉得这个工具好用欢迎关注长安牧笛

相关新闻

嵌入式GUI字体系统深度解析:从位图到TrueType的实战应用

嵌入式GUI字体系统深度解析:从位图到TrueType的实战应用

1. 嵌入式GUI字体系统:从位图到TrueType的深度解析与实战在嵌入式GUI开发里,字体渲染是个既基础又关键的环节。它直接决定了你的产品界面是“能用”还是“好用”。我经历过不少项目,从早期资源捉襟见肘的8位MCU,到如今功能复杂的3…

2026/6/19 16:06:28阅读更多 →
事件驱动的条件预测:Mamba状态空间模型改造实践

事件驱动的条件预测:Mamba状态空间模型改造实践

1. 项目概述:当预测模型开始“预设条件”——一种面向金融决策的新型状态空间建模思路 你有没有试过盯着K线图发呆,不是在猜明天涨还是跌,而是在想:“如果这支股票明天收盘跌破28.5元这个关键支撑位,接下来三天会怎么走…

2026/6/19 16:06:28阅读更多 →
Gemma 4显存占用深度解析:从权重加载到DGA内存陷阱

Gemma 4显存占用深度解析:从权重加载到DGA内存陷阱

1. 项目概述:为什么“显存够不够”是Gemma 4落地的第一道门槛 2026年4月,Google正式发布Gemma 4系列——这不是一次简单迭代,而是从架构底层重构的第三代轻量级开源大模型家族。E4B(4B参数)、26B(26B参数&a…

2026/6/19 16:06:28阅读更多 →
B站视频下载神器:轻松保存大会员4K高清和充电专属视频

B站视频下载神器:轻松保存大会员4K高清和充电专属视频

B站视频下载神器:轻松保存大会员4K高清和充电专属视频 【免费下载链接】bilibili-downloader B站视频下载,支持下载大会员清晰度4K,持续更新中 项目地址: https://gitcode.com/gh_mirrors/bil/bilibili-downloader 你是否曾经在B站上看…

2026/6/19 17:11:34阅读更多 →
勒索软件即服务(RaaS)攻击链条深度解析与纵深防御实战指南

勒索软件即服务(RaaS)攻击链条深度解析与纵深防御实战指南

1. 项目概述:当勒索成为一门“云服务”生意几年前,如果你听到“勒索软件”,脑海里浮现的可能是某个技术高超的黑客,在暗室里敲着代码,精心策划一次攻击。但今天,情况彻底变了。勒索软件攻击的门槛&#xff…

2026/6/19 17:11:34阅读更多 →
Linux打印机兼容性终极指南:foo2zjs驱动套件完全解析

Linux打印机兼容性终极指南:foo2zjs驱动套件完全解析

Linux打印机兼容性终极指南:foo2zjs驱动套件完全解析 【免费下载链接】foo2zjs A linux printer driver for QPDL protocol - copy of http://foo2zjs.rkkda.com/ 项目地址: https://gitcode.com/gh_mirrors/fo/foo2zjs 在Linux系统中寻找合适的打印机驱动常…

2026/6/19 17:11:34阅读更多 →
S12XS微控制器I/O与ADC电气特性深度解析与设计实战

S12XS微控制器I/O与ADC电气特性深度解析与设计实战

1. 项目概述:从数据手册到可靠设计在嵌入式硬件设计的江湖里,数据手册就是我们的“武功秘籍”。但说实话,很多工程师拿到像S12XS这类微控制器的参考手册,翻到电气特性(Electrical Characteristics)章节时&a…

2026/6/19 17:11:34阅读更多 →
深入解析S12X BDM调试:从硬件命令到串行协议的实战指南

深入解析S12X BDM调试:从硬件命令到串行协议的实战指南

1. 项目概述:为什么需要深入理解BDM调试模块?在嵌入式开发,尤其是汽车电子和工业控制领域,调试从来都不是一件轻松的事。当你的代码在飞思卡尔(现恩智浦)S12X这类高性能16位微控制器上运行时,传…

2026/6/19 17:11:34阅读更多 →
【Halcon实战】从RGB到HSV:利用decompose3与trans_from_rgb实现精准彩色图像分割

【Halcon实战】从RGB到HSV:利用decompose3与trans_from_rgb实现精准彩色图像分割

1. 为什么需要从RGB转换到HSV? 在工业视觉检测中,我们经常遇到这样的场景:生产线上需要识别红色零件,但背景中混杂着其他颜色的干扰物。直接用RGB三通道值判断颜色,很容易受光照变化影响——早上和傍晚拍的照片&#x…

2026/6/19 17:06:34阅读更多 →
Photobucket付费墙背后:5美元买童年回忆却落得一场空!

Photobucket付费墙背后:5美元买童年回忆却落得一场空!

1. 付费墙初现如今身处万亿市值公司林立的时代,我们也不能轻易放弃5美元。就像Photobucket,它曾相当于过去的Imgur,我们小时候常把图片上传到这个网站,然后在各种论坛上分享链接,它简单好用,尽职尽责。但最…

2026/6/19 0:04:37阅读更多 →
如何在5分钟内掌握Mermaid Live Editor:实时图表编辑终极指南

如何在5分钟内掌握Mermaid Live Editor:实时图表编辑终极指南

如何在5分钟内掌握Mermaid Live Editor:实时图表编辑终极指南 【免费下载链接】mermaid-live-editor Edit, preview and share mermaid charts/diagrams. New implementation of the live editor. 项目地址: https://gitcode.com/GitHub_Trending/me/mermaid-live…

2026/6/19 0:04:37阅读更多 →
yuzu模拟器内存修改技术深度解析:金手指功能实现原理与实践指南

yuzu模拟器内存修改技术深度解析:金手指功能实现原理与实践指南

yuzu模拟器内存修改技术深度解析:金手指功能实现原理与实践指南 【免费下载链接】yuzu 项目地址: https://gitcode.com/GitHub_Trending/yuz/yuzu yuzu作为目前最流行的开源Nintendo Switch模拟器,不仅提供了完整的游戏运行环境,还内…

2026/6/19 0:04:37阅读更多 →