我如何使用 Electron、React 和 SQLite 构建桌面交易日志
Source: Dev.to
概述
上周,我发布了一款名为 Aurafy 的桌面应用,它是为期货交易者设计的交易日志,完全本地运行——没有云端、没有账户、没有订阅。我想分享其背后的技术决策,因为在处理敏感金融数据的工具中,“本地优先”方法常被低估。
架构
服务器
- Express.js + better‑sqlite3
- 在 Electron 主进程中运行(不生成子进程,从而将启动时间缩短至 2 秒以下)
- SQLite 在 WAL 模式下处理所有持久化
- 每次写入都使用
synchronous = FULL以确保数据持久性
客户端
- React, Vite, Tailwind CSS, Recharts
- 标准单页应用,通过
localhost与 Express 服务器通信 - TanStack Query 负责数据获取和缓存
Electron 包装层
- 主进程在进程内启动 Express 服务器,打开指向
localhost的BrowserWindow,并处理原生功能,如屏幕录制权限和悬浮摄像头窗口。
数据存储与安全
交易数据(盈亏、账户规模、错误)极其敏感。使用 SQLite 时,所有数据都存放在:
~/Library/Application Support/aurafy/data/journal.db- 用户可以自行备份、移动或删除该文件。
- 没有 API 密钥、OAuth 流程或登录提示。
- 权衡:没有跨设备同步,但这并不是问题,因为交易员通常在自己的桌面上记录日志。
内置屏幕录制器
一个关键功能是能够录制交易会话以供后续回顾,类似于运动员观看比赛录像。
Electron 的
desktopCapturerAPI 提供屏幕捕获。与
getUserMedia结合使用以获取麦克风输入。音频流通过 Web Audio API 混合后送入
MediaRecorder。摄像头叠加层在一个独立的
BrowserWindow中运行,配置如下:{ transparent: true, alwaysOnTop: true, frame: false }它会像 Loom 的摄像头气泡一样悬浮在所有应用之上。HTML 只是一段简单的圆形
,其中包含一个显示摄像头画面的元素。
来自交易平台的 CSV 导入
交易者从 Tradovate 和 NinjaTrader 等平台导出 CSV 文件。每个平台使用不同的列名、日期格式和合约命名规则(例如 MNQM6 与 MNQ 06-26)。
我构建了一个解析器,能够:
- 自动检测 平台(通过检查列标题)。
- 规范化 合约名称(使用正则表达式去除合约月份代码)。
- 匹配 本地合约表中的最小变动价位和点值。
- 配对 进出场执行并计算盈亏。
导入流程为:
Drop CSV → preview detected trades → confirm无需手动映射。
性能优化
- 进程内服务器:首个版本为 Express 启动了一个 Node 子进程,导致启动时间增加超过 3 秒,并出现 macOS 代码签名问题(系统将其视为两个独立的应用)。通过
require()在 Electron 主进程中运行 Express,消除了这两个问题。 - SQLite WAL 模式:如果不使用 WAL,写入会阻塞读取。使用
journal_mode = WAL并将synchronous = FULL,在写入期间可以并发读取,并且在崩溃时仍能保证数据持久性。
自动更新挑战
electron-updater 在 GitHub 上创建草稿发布,直到手动发布前会返回 404。我添加了一个 CI 步骤,在 macOS 和 Windows 构建完成后自动发布该发布。
开发注意事项
ELECTRON_RUN_AS_NODE:如果设置了此环境变量(在某些开发环境中很常见),Electron 将以普通 Node.js 运行,require('electron')会返回一个字符串而不是模块。这导致了数小时的调试。
可用性
Aurafy 是免费且可在 . 获取。代码支持期货合约(ES、NQ、CL、MES、MNQ),并具有正确的点值和最小变动价位。
问题
如果您对 Electron + Express + SQLite 架构模式感兴趣,欢迎在评论中提问。