Skip to content

开发指南

面向: 后续开发者。覆盖环境搭建、代码结构、如何加功能/品种/策略、测试、发布。 版本: 1.0.0 | 配套: 02-技术架构


一、开发环境搭建

要求
.NET SDK9.0+(.slnx 格式)
IDEVS 2022 17.10+ / VS2026 / Rider
Python3.10+(采集脚本,打包 exe 用 build_venv)
PostgreSQL15+(可连开发库或本地便携)
Git已配置(Gitee: wenzhou-boyi-network/boyangtong)

首次克隆与运行

bash
git clone https://gitee.com/wenzhou-boyi-network/boyangtong.git
cd boyangtong
# 配置数据库(src/Futures.Desktop/config/appsettings.json,可复制 example)
# Debug 运行(无任何商业化校验限制)
dotnet build Futures.Desktop.slnx
dotnet run --project src/Futures.Desktop

二、代码结构

src/
├─ Futures.Core/           # 核心:模型、数据访问、服务(无 UI)
│  ├─ Models/              # 实体模型
│  ├─ Data/                # 数据服务(Npgsql + Dapper)
│  ├─ Services/            # 业务服务(License/Update/ErrorReport)
│  ├─ Helpers/             # 工具类(OptionMarginCalculator 等)
│  ├─ Logging/             # 日志
│  └─ Tushare/             # Tushare API 客户端
├─ Futures.Desktop/        # 主程序:Shell + 导航 + Views/ViewModels
│  ├─ Views/               # XAML 视图
│  ├─ ViewModels/          # Prism ViewModel
│  └─ Services/            # 托盘通知等
├─ Futures.Module.Futures/ # 期货模块
├─ Futures.Module.Options/ # 期权模块
├─ Futures.Module.Shared/  # 共享 UI/本地化
└─ Futures.Module.Stock/   # 股票模块
script/                    # Python 采集/打包脚本
tools/                     # 厂商工具(LicenseGenerator/ReleasePublisher/server)
tests/Futures.Core.Tests/  # xUnit 单元测试(335 用例)

三、开发规范

分层规则

  • UI 层(Futures.Desktop/Modules)只做展示与交互,业务逻辑在 Core
  • Core 层不依赖 UI,可测试
  • 新功能优先放 Core 服务 + 接口,UI 通过 DI 注入

命名

  • 项目名/命名空间保持 Futures.*(技术代号),产品显示名用「博衍通」
  • 服务用 I XxxService 接口 + XxxService 实现,DI 注册单例
  • 表名小写下划线,列名小写

日志

  • LogManager.CreateLogger("类名")(统一走文件 + system_logs)
  • 不用 Console.WriteLine

四、如何加一个新功能页面

  1. 创建 ViewModel + View
    • src/Futures.Desktop/ViewModels/XxxViewModel.cs(继承 BindableBase)
    • src/Futures.Desktop/Views/XxxView.xaml + .xaml.cs
  2. 注册导航
    • App.xaml.cs: RegisterForNavigation<XxxView, XxxViewModel>("Xxx")
    • ShellWindowViewModel.cs ViewMap: ["Xxx"] = typeof(XxxView)
  3. 加菜单
    • ShellWindow.xaml 系统/对应分组加 Button(Tag="Xxx")
    • UIStrings.resx + UIStrings.cs 加 Menu.Xxx / Tab.Xxx
  4. 业务逻辑:在 Futures.Core 加服务,ViewModel 注入
  5. 测试:Core 逻辑写 xUnit 测试

五、如何加一个品种/合约

  • 品种自动发现: 采集脚本 tq_futures_pg.py 从天勤自动获取,一般无需手动
  • 品种中文名: 「品种名称管理」页面或 product_chinese_names 表
  • 品种参数(乘数/保证金/手续费): 「品种参数」页面 → product_params 表
  • 主力映射: 运行 tq_mapping_pg → fut_mappings
  • 交易时段: product_trading_hours 表(无记录=按全局规则)

六、如何加一个期权策略

45 个策略在 OptionsStrategy.All(src/Futures.Core/Models/OptionsStrategy.cs)。 加新策略(46 号):

  1. CreateAll() 加策略定义(名称/构造/风险/多空权重/复杂度)
  2. OptionsStrategyMatcher.GenerateExecutionPlancase 46:(行权价计算 + 腿文本 + 止盈止损)
  3. OptionsLegResolver 确认腿文本可解析(或加特殊腿处理)
  4. 回测模板: OptionsBacktestService 自动从 All 生成

七、如何加一个交易信号源

  1. 在 Core 写数据源服务(如新 API),返回模型
  2. 在对应研判服务(如 FuturesStrategyService)接入评分
  3. TradingOpportunityService.ScoreOpportunityAsync 加评分维度
  4. 信号落库: signal_history(可加 Source 标识)

八、测试

bash
# 全部测试
dotnet test tests/Futures.Core.Tests/Futures.Core.Tests.csproj
# 单个测试
dotnet test --filter "FullyQualifiedName~AutoTradeExecution"

约定: Core 业务逻辑必须配测试;测试不连真实数据库(用内存/桩)。

九、数据库变更规范

  • 表结构变更:在对应服务 EnsureTableAsyncADD COLUMN IF NOT EXISTS 迁移(幂等)
  • 新表:init_timescaledb.py(采集表)或服务自建(业务表)
  • 不改表结构只加数据:直接脚本/服务写入

十、提交与发布

bash
git add .
git commit -m "feat: 新增X功能"
git push

发布: 07-发布流程(用发布工具或 build_release.ps1)

十一、常见开发任务速查

任务位置
改窗口标题/产品名ShellWindowViewModel / Directory.Build.props
改菜单文案UIStrings.resx
加定时任务SchedulerConfigService 默认任务列表
加依赖 DB 的后台服务注册在模块,启动在 App.StartBackgroundDbServices()(见第十二节)
改自动执行逻辑AutoTradeExecutionService
改交易时间判定TradingTimeHelper / ProductSessionService
改行情采集script/*.py(改后需重新 build_exe)
改数据库备份DatabaseMaintenanceService

⚠️ WPF 下拉绑定坑(踩过):ComboBox 的 ItemsSource 若绑定 ValueTuple 列表(如 (string Value, string Label)),DisplayMemberPath="Label" 会因元组无此公开属性而下拉空白。必须用带 Value/Label 属性的普通类(见 SettingsViewModel.QuoteModeOption)。

十二、新增数据库功能规范(首启时序)

背景:主窗口(ShellWindow/Dashboard 等)在首启向导之前显示,而向导完成前数据库尚未创建/配置。 若在向导完成前执行 DB 查询或启动依赖 DB 的后台服务,会反复报 Failed to connect to 127.0.0.1:5432(SocketException 10061)并刷屏。 2026-08 曾三度踩坑(模块 OnInitialized 自启动、ViewModel 构造查库、窗口 Loaded 查库),以下规范务必遵守。

三条铁律

  1. 依赖 DB 的后台服务 → 统一在 App.StartBackgroundDbServices() 启动

    • ❌ 禁止在 Module.OnInitialized、服务构造函数、属性初始化中自启动
    • ✅ 模块只 RegisterTypes 注册;启动逻辑放 StartBackgroundDbServices()(向导/激活弹窗关闭后执行)
    • 参考:StockModule(数据采集调度器 + 股价预警已按此迁移)
    • 注意:IModule.OnInitialized 是接口必需成员,移除服务后要留空实现
  2. 早于向导显示的 DB 查询 → 等待 DatabaseReadiness.WaitAsync()

    • 主窗口在向导前显示,其启动期查询(Dashboard 刷新、今日提醒等)必须等待
    • await DatabaseReadiness.WaitAsync();(已就绪时零开销,直接返回)
    • 用户手动打开(点导航才创建)的页面无需等待(届时向导已完成)
  3. 构造函数不做 DB 调用

    • 构造查库会在容器解析的任意时刻触发,且必然早于向导完成

自动防护基建(新功能推荐用法)

场景用法
通过连接工厂建连await _factory.CreateConnectionReadyAsync()(自动等待就绪后返回连接)
一次性 DB 操作await DatabaseReadiness.ExecuteAsync(() => QueryAsync(...))
纯等待门控await DatabaseReadiness.WaitAsync()
  • DatabaseReadinesssrc/Futures.Core/Data/DatabaseReadiness.cs):静态门控。 MarkReady()App.StartBackgroundDbServices() 调用(幂等,仅首次生效);置位后 WaitAsync() 立即返回。
  • IDbConnectionFactory.CreateConnectionReadyAsync():就绪后返回连接。新代码建连用它替代 CreateConnection() 即自动获得防护,无需单独记忆等待。

接入检查清单(新增 DB 功能时逐项打勾)

  • [ ] 后台定时服务 → 注册在模块,启动在 StartBackgroundDbServices()
  • [ ] Shell 初始显示的页面查询 → 已 await DatabaseReadiness.WaitAsync() 或使用 CreateConnectionReadyAsync()
  • [ ] 构造函数无 DB 调用
  • [ ] 编译 + 测试通过;首次安装场景(删库重装)冒烟无 Npgsql 连接报错

与发布流程的关系

新增 DB 功能不需要修改发布流程build_release.ps1/发布工具为通用全量覆盖), 只需遵守上述时序规范;发布后到 publish\futures-1.0.0 做一次首次安装冒烟验证。

瓯衍期货分析系统 · 温州博益网络科技有限公司