在量化交易、私募基金或多账户资产管理场景中,业务数据通常非常分散:账户余额在交易所或券商系统中,策略状态在研究或交易系统中,订单明细在执行系统中,收益与费用又需要通过报表单独计算。随着账户和策略数量增加,依靠人工表格汇总很快会变得低效,也容易造成数据延迟、口径不一致甚至风险遗漏。
本项目是一套面向量化资产管理业务的管理平台。它通过 React 前端和 Django REST Framework 后端,将账户、资产、策略、订单、风控和收益分析集中在同一个系统中。用户可以从账户总览进入具体子账户,查看实时资产和变化趋势;可以管理策略和交易信号,跟踪委托与成交状态;还可以通过盈亏、费用、持仓和净值等图表理解业务运行情况。
项目背景
这是我在 2022 年就职期间参与的一个项目。当时,公司已经拥有一套量化策略,但针对策略实盘运行情况,尚未建立完善、统一的监控系统。账户资金、策略信号、订单执行、实时资产、盈亏变化和风险信息分散在不同环节,难以被及时、集中地追踪。作为量化小组成员,我参与了这套量化实盘监控系统的开发与维护工作,希望通过统一的平台,为策略实盘运行提供更清晰的可视化和管理能力。由于与原公司存在三年的保密约定,我一直没有公开介绍这段经历;今年约定期满,便想整理并记录项目的基本情况。本文将聚焦系统架构、功能设计与工程实现。
在当时的业务场景下,策略本身已经具备一定的运行能力,但实盘之后的状态缺少一个统一的观察入口。比如,某个策略当天发出了多少信号、这些信号是否转化为真实订单、订单是否成交、成交后的资产变化如何、某个账户是否出现异常波动,这些信息往往需要在多个地方分别查询。
对于量化团队来说,策略研究只是第一步,策略能否稳定地进入实盘、是否按预期执行、风险是否处于可控范围,同样重要。因此,这套系统的定位并不是“生成策略”,而是作为策略实盘运行的监控与管理平台,为交易员、运营人员和管理人员提供统一的数据视图。
一、项目解决了什么问题
一个典型的量化实盘流程,通常会涉及策略、账户、风控、订单、成交和收益等多个环节。任何一个环节出现问题,都可能影响最终结果。
例如,策略本身可能正常输出信号,但由于账户资金不足、风控限制、交易所连接异常或市场流动性不足,订单并不一定能够正常成交。即便订单已经成交,也还需要继续观察资产、仓位、费用和净值是否按预期变化。
项目希望解决的核心问题包括:
- 多层级账户与真实交易账户难以统一管理;
- 初始资产、实时资产和资产变动缺乏统一视图;
- 策略信号与实际交易执行之间缺少追踪链路;
- 委托订单和成交订单难以快速对照;
- 风控信息分散,异常情况不容易及时发现;
- 盈亏、费用、持仓、资金池等指标需要人工统计;
- 管理人员难以快速判断策略的实盘运行状态。
因此,系统并不是简单的“数据展示工具”,而是将交易相关数据集中起来,形成从账户到订单、从策略到收益、从异常发现到风险处理的完整业务链路。
二、系统整体设计
项目采用前后端分离架构。前端负责页面交互、表格展示和图表可视化;后端负责业务逻辑、数据查询、权限控制和接口输出;底层数据由数据库和缓存服务支撑。
这种架构的关键在于职责分离。
前端不直接访问数据库,而是通过 API 获取统一格式的数据;后端不需要关心每个页面如何布局,而是专注于数据计算、数据权限和业务规则。这样的边界设计能够降低系统复杂度,也方便后续独立升级前端或后端。
在实际开发中,前端页面可以围绕业务模块快速迭代;后端则可以把账户、订单、策略、报表等数据以标准接口提供出来。对于内部管理系统而言,这种方式既便于多人协作,也更容易排查问题。
三、核心功能模块
1. 账户与资产管理
账户模块是整个系统的数据基础。量化实盘并不是只有一个账户,实际业务中往往存在母账户、子账户、交易员账户和交易所真实账户等多种层级。
前端接口配置中定义了对应的账户接口:
// 账户
export const PARENTS_PATH = '/account/parents/'; // 母账户
export const EOAS_PATH = '/account/admin_eoa/'; // 管理员从属下的外部账户
export const SUBS_PATH = '/account/parent_subs/'; // 母账户从属下的子账户
export const TRADER_SUBS_PATH = '/account/trader_subs/'; // 交易员从属下的子账户
export const TRADE_ACCOUNTS_PATH = '/account/exchange_trade_accounts/'; // 子账户下的真实账户
这种层级模型能够解决两个问题:一是支持从总体资金池到具体交易账户的逐层查看;二是让资产汇总、权限划分和交易归属更加清晰。
例如,管理人员可以先查看某个母账户的总体资产情况,再进入对应子账户,最后定位到具体交易所或实际交易账户。交易员则可以重点关注与自己相关的子账户和订单。
除账户关系外,系统还提供了初始资产、实时资产和资产变化等页面。
// 固定资产
export const SUB_ASSETS_PATH = '/assets/sub/';
export const PARENT_ASSETS_PATH = '/assets/parent/';
// 实时资产
export const CURRENT_PARENT_PATH = '/current/parent/';
export const CURRENT_SUB_PATH = '/current/sub/';
// 资产变化
export const VARIATION_PARENT_PATH = '/variation/parent/';
export const VARIATION_SUB_PATH = '/variation/sub/';
初始资产能够帮助用户确认账户建立时的资金基数;实时资产用于观察当前资产状态;资产变化页面则更适合分析一段时间内资金、净值或仓位的变化趋势。
对于资产管理系统而言,“当前数值”固然重要,但“变化过程”同样重要。一个账户当前净值正常,不代表其运行一定稳定;如果短时间内出现大幅回撤、频繁资金进出或异常波动,只有结合变化趋势和历史流水才能判断原因。
2. 策略库与信号输出
策略模块主要包含策略库和信号输出两个方向。
策略库用于集中维护策略相关信息,例如策略名称、所属账户、运行状态、配置项和风险控制参数等。信号输出则用于展示策略在实盘运行过程中产生的交易信号。
从业务角度看,策略信号不是最终交易结果,而是交易链路中的一个中间环节。一个信号在进入市场前,通常还需要经过风控校验和订单执行。
将策略库和信号输出独立出来,可以帮助团队观察以下问题:
- 当前有哪些策略在运行;
- 某个策略最近产生了哪些交易信号;
- 信号是否频繁出现或长时间未出现;
- 信号是否被风控规则拦截;
- 信号生成后是否成功转化为订单;
- 策略运行状态是否与资产或收益变化相匹配。
从系统设计角度看,这种拆分避免了把策略配置、信号数据和订单数据混在同一个页面中。策略相关页面关注策略“想做什么”,订单页面关注交易“实际做了什么”,而报表页面关注最终“产生了什么结果”。
3. 订单管理:委托与成交分离
订单模块包含委托订单和成交订单。
委托订单表示系统或交易员向市场发送的交易指令。它可能还在等待成交、部分成交、完全成交、撤销或被拒绝。成交订单则表示已经完成的交易执行结果。
前端中对应的接口定义如下:
// 订单管理
export const ORDER_ENTRUSTMENT_PATH = '/order/entrustment/';
export const ORDER_EXECUTION_PATH = '/order/execution/';
将委托和成交分开管理,是交易系统中非常常见且必要的做法。因为“发出了订单”并不等于“完成了交易”。
例如,策略生成买入信号后,系统可能会创建一笔买入委托。由于市场价格变动、流动性不足或交易所规则限制,这笔委托可能只成交一部分,也可能被撤销或拒绝。
通过分别展示委托与成交信息,用户能够更准确地定位问题:
- 是策略没有产生信号;
- 还是信号没有进入订单系统;
- 是订单没有正常提交;
- 还是订单提交后没有成交;
- 是成交价格偏离预期;
- 还是最终成交导致的资产变化异常。
这类追踪能力对于实盘运行尤为重要,因为它能帮助团队快速区分策略问题、风控问题、执行问题和市场问题。
4. 风控输入、风控输出与通知
在量化实盘中,风控不是一个可选功能,而是策略运行的必要保障。
风控可能涉及资金比例、持仓比例、单笔交易规模、累计亏损、策略状态、交易频率、交易品种限制等多个维度。系统中的风控输入和风控输出接口,体现了对风险检查过程的模块化设计。
// 风控输入
export const RISK_INPUT_PATH = '/risk/input/';
export const RISK_OUTPUT_PATH = '/risk/output/';
可以将风控输入理解为需要检测的数据与规则参数,将风控输出理解为检测后给出的结果、风险等级或处理建议。
系统还配置了风险报告页面:
{
path: "/risk-report",
exact: false,
name: "通知",
component: RiskReport,
auth: [1]
}
通知页面的价值在于把风险信息从后台日志中“带到前台”。当某些异常发生时,交易员或管理人员可以在统一页面中查看和处理,而不是依赖人工检查多个系统。
一个健全的风控系统,不只是“告诉用户发生了风险”,还需要帮助用户形成发现、确认、处理和留痕的闭环。
5. 盈亏、费用与数据可视化报表
对于管理人员而言,账户余额和订单明细只是基础数据,更重要的是理解整体经营表现。因此,项目中包含 PnL Report 和 Fees Report 两类报表模块。
PnL 是 Profit and Loss 的缩写,即盈亏报表;Fees Report 则主要用于分析交易、资金或投资过程中产生的费用。
路由中对应的页面入口如下:
{
path: "/pnl/info",
exact: false,
name: "",
component: PnlReport,
auth: [1]
},
{
path: "/fees/info",
exact: false,
name: "",
component: FeesReport,
auth: [1]
}
项目中已有多种图表页面和组件,涵盖净值、最大盈亏、持仓、资金池、健康度、债务以及分钟级净值等内容。
// 图表数据
export const GET_CHARTS_DATA = '/charts/data/';
通过统一的图表数据接口,后端可以先对原始数据进行统计和聚合,再返回给前端。前端则根据返回数据绘制折线图、饼图、柱状图或其他统计图表。
不同类型的展示方式承担不同任务:
- 表格适合精确查看数据、筛选和导出;
- 折线图适合观察资产、净值和收益的时间趋势;
- 饼图适合展示资产、账户或持仓的结构分布;
- 柱状图适合比较不同账户、策略或时间段的表现;
- 指标卡片适合快速呈现总资产、累计盈亏、费用和风险状态。
这种表格与图表结合的方式,可以让用户同时获得“明细”和“趋势”两种视角。
四、前端实现思路
前端使用 React 构建,项目基于 Create React App 搭建,并通过 react-app-rewired 扩展配置。
{
"scripts": {
"start": "react-app-rewired start",
"build": "react-app-rewired build",
"test": "react-app-rewired test"
}
}
项目中使用的主要技术包括:
- React:构建页面和可复用组件;
- React Router:管理账户、策略、订单和报表等页面路由;
- Redux:管理跨页面共享状态;
- Ant Design:提供后台管理常用组件;
- Axios:负责调用后端 API;
- ECharts 与 Chart.js:负责数据可视化;
- Sass:用于页面样式组织。
1. 按业务领域划分页面
前端页面按账户、策略、订单、报表等领域拆分,例如:
views/
├── Account/
│ ├── Info/
│ ├── Original/
│ ├── Latest/
│ └── Difference/
├── Strategy/
│ ├── Square/
│ └── Signal/
├── Order/
│ ├── Entrustment/
│ └── Execution/
├── PnlReport/
├── FeesReport/
└── RiskReport/
这种目录结构与实际业务概念保持一致。开发人员需要修改账户功能时,可以集中在 Account 模块中处理;需要增加订单功能时,则主要关注 Order 模块。相比所有页面文件混在一起,这种结构更适合长期维护。
2. 路由与按需加载
项目通过 React Router 定义各页面路由,并使用动态加载组件减少首次加载体积。
const AccountInfo = loadable(() =>
import(/* webpackChunkName: 'info' */ "../views/Account/Info")
);
const StrategySquare = loadable(() =>
import(/* webpackChunkName: 'info' */ "../views/Strategy/Square")
);
路由配置则将访问路径、页面名称、组件和权限要求放在一起:
{
path: "/account/info",
exact: false,
name: "账户信息",
component: AccountInfo,
auth: [1]
},
{
path: "/strategy/square",
exact: false,
name: "策略库",
component: StrategySquare,
auth: [1]
},
{
path: "/order/entrustment",
exact: false,
name: "委托订单",
component: OrderEntrustment,
auth: [1]
}
按需加载的思路是:用户访问账户模块时,再加载账户相关代码;访问报表模块时,再加载图表和报表相关代码。对于图表较多、页面较复杂的后台系统,这能改善首次打开时的加载体验。
3. 组件化页面设计
以账户信息模块为例,页面并没有把所有内容堆在一个文件中,而是拆分为账户信息面板、资产表格、交易流水表格和编辑抽屉等组件。
Account/Info/
├── AccountInfoPane.jsx
├── MainInfoPane.jsx
├── SubInfoPane.jsx
├── MainAssetsTable.jsx
├── AssetsTable.jsx
├── MainTransTable.jsx
├── AccountTransTable.jsx
└── SubAssetsDrawerForm.jsx
这种组件化设计带来了几个好处:
- 页面职责更清晰;
- 组件可以复用;
- 表格、表单和图表可以独立维护;
- 复杂页面更容易定位问题;
- 后续新增账户字段或操作时影响范围更小。
4. 接口集中管理
项目将 API 路径集中定义在配置文件中,而不是把接口地址散落在不同组件内。
export const API = process.env.REACT_APP_API;
// 账户
export const PARENTS_PATH = '/account/parents/';
// 策略与风控
export const RISK_INPUT_PATH = '/risk/input/';
export const RISK_OUTPUT_PATH = '/risk/output/';
// 订单
export const ORDER_ENTRUSTMENT_PATH = '/order/entrustment/';
export const ORDER_EXECUTION_PATH = '/order/execution/';
这是一项非常实用的工程化实践。当前端需要切换开发、测试和生产环境时,只需要修改环境变量中的 API 地址,而不用逐个修改业务页面。
例如:
开发环境:REACT_APP_API=http://localhost:8000
测试环境:REACT_APP_API=https://test-api.example.com
生产环境:REACT_APP_API=https://api.example.com
接口路径集中管理后,如果后端调整某个接口,也可以更快找到需要修改的位置。
五、后端实现思路
后端使用 Django REST Framework 构建。Django 提供了成熟的 ORM、配置机制和安全能力,Django REST Framework 则适合将业务能力封装成标准 REST API。
从已有项目说明中可以看到,后端按不同业务领域划分了多个模块,包括账户、图表、实时数据、资金、策略、关系和结算配置等。
imcservice/
├── account/
├── charts/
├── current/
├── custom/
├── funds/
├── imcadmin/
├── relation/
├── resource/
├── settleconfig/
└── strategy/
这样的模块划分与前端的业务结构相对应。账户模块负责账户关系和账户数据;current 模块负责实时数据;charts 模块负责图表所需的聚合数据;strategy 模块负责策略相关功能;funds 模块处理资金和流水。
后端请求的基本处理流程如下:
数据库使用 MySQL,适合保存账户、订单、交易记录和配置类业务数据;Redis 则可以用于缓存热点数据、降低重复查询压力,或支持部分实时场景。
后端生产环境可以通过 Gunicorn 启动 WSGI 服务:
gunicorn -w 4 --bind 0.0.0.0:8989 imcservice.wsgi:application
在实际部署中,通常还会配合 Nginx 进行反向代理和静态资源服务,从而形成较常见的 Python Web 服务部署架构。
六、实现过程中的关键思路
1. 先梳理数据关系,再实现页面
这类系统的难点不只在于页面数量,更在于业务对象之间的关联关系。
一个典型的数据关系可以概括为:
如果在开发前没有梳理清楚这些关系,后续很容易出现账户归属不明确、订单无法追溯到策略、报表口径不一致等问题。
因此,实现时应优先确认:
- 账户的层级结构;
- 策略与账户之间的绑定关系;
- 信号与订单之间的关联字段;
- 委托与成交之间的状态关系;
- 成交如何影响资产、持仓和盈亏;
- 风控规则在哪个环节生效;
- 报表指标的计算口径与更新时间。
2. 以业务流程组织页面,而非单纯按数据表组织
用户关心的往往不是数据库中有哪些表,而是如何完成工作。
例如,一个交易员进入系统后,可能先查看账户实时资产,再查看策略信号,然后检查委托订单和成交订单,最后通过风险通知确认是否存在异常。页面设计应尽量贴近这种业务路径。
通过将账户、策略、订单和报表模块串联起来,系统能更好地支持日常实盘监控工作。
3. 表格与图表交叉验证
对于资金和收益类数据,图表能帮助用户快速发现趋势,但最终判断往往仍需要明细数据支持。
例如,净值曲线出现异常下跌时,用户需要进一步查看具体账户资产变化、交易流水或成交订单;某策略收益较好时,也需要通过订单与费用数据确认收益来源。
因此,较合理的页面设计通常是:
- 顶部展示核心指标;
- 中部展示趋势图或结构图;
- 底部提供可筛选的明细表格;
- 必要时允许从图表或汇总数据跳转到具体记录。
这种设计能够兼顾快速浏览与深入排查。
七、后续可优化方向
虽然项目已经具备账户、策略、订单、风控和报表等核心能力,但如果继续演进,还可以从以下几个方向优化。
1. 升级前端技术栈
项目使用的 React 和 Create React App 版本相对较早。后续可考虑升级到新版 React,并使用 Vite 等现代构建工具提升本地开发、热更新和生产构建效率。
2. 完善自动化测试
账户、订单、风控和报表属于关键模块,应逐步补充测试覆盖。
测试重点可以包括:
- 账户层级关系是否正确;
- 订单状态是否按预期流转;
- 风控规则是否能够正确拦截;
- 权限是否限制了数据访问范围;
- 报表计算结果是否符合统一口径;
- 异常接口和空数据是否能被页面正确处理。
3. 建立统一的数据字典
报表系统最容易出现的问题,是同一个指标在不同页面有不同含义。比如“资产”“净值”“可用资金”“累计盈亏”是否包含手续费、是否包含冻结资金、按什么时间更新,都需要有明确说明。
后续可以建立统一数据字典,明确指标定义、数据来源、更新时间和计算方式,减少跨团队沟通成本。
4. 加强权限与操作审计
资产管理系统通常需要更细粒度的权限设计。管理员、交易员、风控人员和只读用户应当具备不同的数据访问和操作权限。
同时,对于修改账户配置、调整策略参数、撤销订单、处理风险通知等关键操作,应保留完整的操作记录,以便后续追踪和审计。
5. 提升实时性与告警能力
对于实时资产、订单状态和风险事件,可以进一步引入消息队列、WebSocket 或定时任务,使信息能更及时地推送到页面或通知渠道。
这样可以减少用户反复刷新页面的操作,也有助于让异常问题更早被发现和处理。
八、总结
这个项目是一套面向量化交易与资产管理场景的实盘监控平台。它以账户和资产为基础,以策略信号和订单执行为交易链路,以风控通知和数据报表为管理手段,将原本分散的业务信息集中到统一系统中。
在功能层面,系统覆盖了多层级账户管理、初始与实时资产查看、资产变化追踪、策略库、信号输出、委托订单、成交订单、风险通知、盈亏报表和费用报表等能力。
在技术层面,React 前端与 Django REST Framework 后端组成了前后端分离架构。React Router 负责路由组织,Redux 支持状态管理,Ant Design 提供后台界面组件,Axios 完成接口请求,ECharts 与 Chart.js 用于数据可视化;后端通过 Django、MySQL 和 Redis 提供业务数据与服务支撑。
回顾这个项目,我认为它最有价值的地方并不是某一个页面或某一个接口,而是将策略、交易、资金和风险信息串联起来,形成了一套可查询、可追踪、可分析、可管理的实盘监控体系。这段经历也让我更加直观地理解到:量化策略的价值不仅在于研究和回测,更在于如何让策略在真实环境中稳定、透明、可控地运行。