从账户管理到风险报表:一个量化资产管理平台的设计与实现

在量化交易、私募基金或多账户资产管理场景中,业务数据通常非常分散:账户余额在交易所或券商系统中,策略状态在研究或交易系统中,订单明细在执行系统中,收益与费用又需要通过报表单独计算。随着账户和策略数量增加,依靠人工表格汇总很快会变得低效,也容易造成数据延迟、口径不一致甚至风险遗漏。

本项目是一套面向量化资产管理业务的管理平台。它通过 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 提供业务数据与服务支撑。

回顾这个项目,我认为它最有价值的地方并不是某一个页面或某一个接口,而是将策略、交易、资金和风险信息串联起来,形成了一套可查询、可追踪、可分析、可管理的实盘监控体系。这段经历也让我更加直观地理解到:量化策略的价值不仅在于研究和回测,更在于如何让策略在真实环境中稳定、透明、可控地运行。