鸿蒙app 理财产品推荐(风险等级匹配)【华为云根技术】
【摘要】 引言在鸿蒙生态中,理财产品推荐系统可根据用户风险承受能力匹配合适的投资产品,提升个性化服务与用户信任度。通过风险等级评估与产品属性匹配,实现精准推荐、动态调整与可视化展示。技术背景鸿蒙框架:Stage 模型,@Component构建 UI,Preferences/关系型数据库存储用户信息与风险测评结果,@ohos.chart可视化收益与风险分布。风险等级模型:常用五级分类(保守型、稳健型、平...
引言
在鸿蒙生态中,理财产品推荐系统可根据用户风险承受能力匹配合适的投资产品,提升个性化服务与用户信任度。通过风险等级评估与产品属性匹配,实现精准推荐、动态调整与可视化展示。
技术背景
-
鸿蒙框架:Stage 模型,
@Component构建 UI,Preferences/关系型数据库存储用户信息与风险测评结果,@ohos.chart可视化收益与风险分布。 -
风险等级模型:常用五级分类(保守型、稳健型、平衡型、成长型、进取型),依据用户年龄、收入、投资经验、风险承受意愿评分。
-
匹配算法:基于规则或简单加权评分,将用户风险等级与理财产品风险等级匹配。
-
数据安全:用户财务数据本地加密存储,符合鸿蒙 TEE 与权限模型。
应用使用场景
-
银行理财 App:新用户完成风险测评后推荐适配产品。
-
证券/基金平台:根据用户等级展示可购买的基金类型。
-
智能投顾:定期重评风险等级并调整推荐列表。
-
企业员工福利平台:按职级与年龄批量匹配定投计划。
核心特性
-
风险测评问卷:动态生成问题并计算得分。
-
多维度匹配:支持按风险、期限、收益率过滤。
-
实时调整:用户手动更新测评或系统定期重算。
-
可视化对比:产品收益与风险雷达图展示。
原理流程图与原理解释
流程图
graph TD
A[用户进入理财模块] --> B{是否已完成风险测评?}
B -->|否| C[展示风险测评问卷]
C --> D[计算风险得分与等级]
B -->|是| E[读取用户风险等级]
D & E --> F[从产品库筛选匹配产品]
F --> G[排序与推荐展示]
G --> H[用户查看详情/购买]
H --> I[定期/手动重评风险]
I --> D
原理解释
-
风险测评:问卷每题赋予权重,累加得分映射到五级风险等级。
-
产品匹配:产品标注风险等级(如 R1~R5),仅展示等级≤用户等级的理财产品。
-
推荐排序:可按预期收益、流动性、历史波动率综合排序。
-
可视化:雷达图展示产品在收益、风险、期限等维度的属性。
环境准备
-
DevEco Studio 4.0+
-
SDK API 9+(支持数据库、图表、权限)
-
权限:
"requestPermissions": [
{ "name": "ohos.permission.READ_USER_STORAGE" },
{ "name": "ohos.permission.WRITE_USER_STORAGE" }
]
不同场景下详细代码实现
1. 数据模型(Model/FinanceModel.ts)
// 风险等级
export enum RiskLevel {
CONSERVATIVE = 1, // 保守型
STABLE = 2, // 稳健型
BALANCED = 3, // 平衡型
GROWTH = 4, // 成长型
AGGRESSIVE = 5 // 进取型
}
// 用户风险信息
export class UserRiskProfile {
userId: string;
riskLevel: RiskLevel;
score: number; // 0~100
age: number;
income: number;
experienceYears: number;
constructor(userId: string, riskLevel: RiskLevel, score: number, age: number, income: number, experienceYears: number) {
this.userId = userId;
this.riskLevel = riskLevel;
this.score = score;
this.age = age;
this.income = income;
this.experienceYears = experienceYears;
}
}
// 理财产品
export class FinancialProduct {
id: string;
name: string;
riskLevel: RiskLevel;
expectedAnnualReturn: number; // 百分比
termMonths: number;
minAmount: number;
constructor(id: string, name: string, riskLevel: RiskLevel, expectedAnnualReturn: number, termMonths: number, minAmount: number) {
this.id = id;
this.name = name;
this.riskLevel = riskLevel;
this.expectedAnnualReturn = expectedAnnualReturn;
this.termMonths = termMonths;
this.minAmount = minAmount;
}
}
2. 风险测评与匹配服务(Service/RiskMatchService.ts)
import { UserRiskProfile, FinancialProduct, RiskLevel } from '../Model/FinanceModel';
import relationalStore from '@ohos.data.relationalStore';
export class RiskMatchService {
private rdbStore: relationalStore.RdbStore | null = null;
async init(context: Context) {
this.rdbStore = await relationalStore.getRdbStore(context, {
name: 'finance.db',
securityLevel: relationalStore.SecurityLevel.S1
});
await this.createTables();
await this.initProducts();
}
private async createTables() {
const userSql = `CREATE TABLE IF NOT EXISTS user_risk (
user_id TEXT PRIMARY KEY,
risk_level INTEGER,
score INTEGER,
age INTEGER,
income REAL,
experience_years INTEGER
)`;
const productSql = `CREATE TABLE IF NOT EXISTS product (
id TEXT PRIMARY KEY,
name TEXT,
risk_level INTEGER,
expected_annual_return REAL,
term_months INTEGER,
min_amount REAL
)`;
await this.rdbStore!.executeSql(userSql);
await this.rdbStore!.executeSql(productSql);
}
private async initProducts() {
const count = await this.getProductCount();
if (count > 0) return;
const products: FinancialProduct[] = [
new FinancialProduct('P001', '稳盈宝', RiskLevel.CONSERVATIVE, 2.5, 3, 1000),
new FinancialProduct('P002', '安益计划', RiskLevel.STABLE, 4.0, 6, 5000),
new FinancialProduct('P003', '均衡增长', RiskLevel.BALANCED, 6.0, 12, 10000),
new FinancialProduct('P004', '进取先锋', RiskLevel.GROWTH, 8.5, 24, 20000),
new FinancialProduct('P005', '极速增值', RiskLevel.AGGRESSIVE, 12.0, 36, 50000)
];
for (const p of products) {
await this.rdbStore!.insert('product', {
'id': p.id,
'name': p.name,
'risk_level': p.riskLevel,
'expected_annual_return': p.expectedAnnualReturn,
'term_months': p.termMonths,
'min_amount': p.minAmount
});
}
}
private async getProductCount(): Promise<number> {
const resultSet = await this.rdbStore!.query(new relationalStore.RdbPredicates('product'), ['COUNT(*) as c']);
resultSet.goToNextRow();
const c = resultSet.getLong(resultSet.getColumnIndex('c'));
resultSet.close();
return c;
}
// 计算风险等级
calculateRiskLevel(age: number, income: number, experienceYears: number, quizScore: number): { level: RiskLevel, score: number } {
let score = quizScore;
// 年龄权重
if (age < 30) score += 15;
else if (age < 50) score += 10;
else score += 0;
// 收入权重
if (income > 200000) score += 20;
else if (income > 100000) score += 10;
else score += 0;
// 经验权重
if (experienceYears > 5) score += 15;
else if (experienceYears > 2) score += 10;
else score += 0;
let level: RiskLevel;
if (score >= 80) level = RiskLevel.AGGRESSIVE;
else if (score >= 60) level = RiskLevel.GROWTH;
else if (score >= 40) level = RiskLevel.BALANCED;
else if (score >= 20) level = RiskLevel.STABLE;
else level = RiskLevel.CONSERVATIVE;
return { level, score };
}
async saveUserProfile(profile: UserRiskProfile) {
await this.rdbStore!.insert('user_risk', {
'user_id': profile.userId,
'risk_level': profile.riskLevel,
'score': profile.score,
'age': profile.age,
'income': profile.income,
'experience_years': profile.experienceYears
});
}
async getUserProfile(userId: string): Promise<UserRiskProfile | null> {
const pred = new relationalStore.RdbPredicates('user_risk').equalTo('user_id', userId);
const rs = await this.rdbStore!.query(pred, ['*']);
let profile: UserRiskProfile | null = null;
if (rs.goToNextRow()) {
profile = new UserRiskProfile(
rs.getString(rs.getColumnIndex('user_id')),
rs.getLong(rs.getColumnIndex('risk_level')) as RiskLevel,
rs.getLong(rs.getColumnIndex('score')),
rs.getLong(rs.getColumnIndex('age')),
rs.getDouble(rs.getColumnIndex('income')),
rs.getLong(rs.getColumnIndex('experience_years'))
);
}
rs.close();
return profile;
}
// 匹配产品
async matchProducts(userId: string): Promise<FinancialProduct[]> {
const profile = await this.getUserProfile(userId);
if (!profile) return [];
const pred = new relationalStore.RdbPredicates('product').lessThanOrEqualTo('risk_level', profile.riskLevel);
const rs = await this.rdbStore!.query(pred, ['*']);
const list: FinancialProduct[] = [];
while (rs.goToNextRow()) {
list.push(new FinancialProduct(
rs.getString(rs.getColumnIndex('id')),
rs.getString(rs.getColumnIndex('name')),
rs.getLong(rs.getColumnIndex('risk_level')) as RiskLevel,
rs.getDouble(rs.getColumnIndex('expected_annual_return')),
rs.getLong(rs.getColumnIndex('term_months')),
rs.getDouble(rs.getColumnIndex('min_amount'))
));
}
rs.close();
return list.sort((a, b) => b.expectedAnnualReturn - a.expectedAnnualReturn);
}
}
3. UI 界面(pages/Index.ets)
import { RiskMatchService } from '../Service/RiskMatchService';
import { UserRiskProfile, FinancialProduct, RiskLevel } from '../Model/FinanceModel';
@Entry
@Component
struct FinanceRecommendPage {
@State userProfile: UserRiskProfile | null = null;
@State recommended: FinancialProduct[] = [];
@State showQuiz: boolean = false;
@State quizScore: number = 50;
private service: RiskMatchService = new RiskMatchService();
private userId: string = 'user001';
aboutToAppear() {
this.service.init(getContext()).then(() => this.loadData());
}
async loadData() {
this.userProfile = await this.service.getUserProfile(this.userId);
if (this.userProfile) {
this.recommended = await this.service.matchProducts(this.userId);
}
}
startQuiz() {
this.showQuiz = true;
}
async finishQuiz() {
// 假设年龄、收入、经验固定
const age = 35;
const income = 150000;
const exp = 3;
const { level, score } = this.service.calculateRiskLevel(age, income, exp, this.quizScore);
const profile = new UserRiskProfile(this.userId, level, score, age, income, exp);
await this.service.saveUserProfile(profile);
this.showQuiz = false;
this.loadData();
}
build() {
Column({ space: 20 }) {
Text('理财产品推荐').fontSize(24).fontWeight(FontWeight.Bold);
if (!this.userProfile) {
Button('开始风险测评').onClick(() => this.startQuiz());
} else {
Text(`您的等级: ${RiskLevel[this.userProfile.riskLevel]} (得分:${this.userProfile.score})`)
.fontSize(16).fontColor(Color.Blue);
}
if (this.showQuiz) {
Text('风险测评(示例滑动条)').fontSize(18);
Slider({ value: this.quizScore, min: 0, max: 100, step: 1 })
.onChange(val => this.quizScore = val);
Button('完成测评').onClick(() => this.finishQuiz());
}
Text('推荐产品').fontSize(18);
List() {
ForEach(this.recommended, (p: FinancialProduct) => {
ListItem() {
Column() {
Text(p.name).fontSize(16).fontWeight(FontWeight.Medium);
Text(`风险:${RiskLevel[p.riskLevel]} | 年化:${p.expectedAnnualReturn}% | 期限:${p.termMonths}月 | 起购:¥${p.minAmount}`)
.fontSize(14).fontColor(Color.Gray);
}.width('100%').padding(10);
}
})
}.width('100%').flexGrow(1);
}.width('100%').height('100%').padding(16)
}
}
实际详细应用代码示例实现
见以上
RiskMatchService与 UI 完整代码。运行结果
-
初次进入提示“开始风险测评”。
-
完成测评后显示用户风险等级与匹配产品列表,按收益率降序排列。
测试步骤以及详细代码
-
初始化数据库并插入产品数据。
-
模拟用户测评,调整
quizScore观察等级变化。 -
验证匹配产品列表仅包含风险等级≤用户等级的项。
部署场景
-
银行 App:新用户开户后引导测评并推荐。
-
基金销售平台:按风险开放可买产品池。
-
智能投顾终端:大厅一体机提供快速测评与推荐。
疑难解答
-
匹配结果为空:检查产品库是否初始化、风险等级映射是否正确。
-
测评等级不变:确认
calculateRiskLevel权重逻辑与输入参数有效。 -
数据库初始化失败:检查表结构 SQL 与权限。
未来展望
-
AI 推荐:引入机器学习模型,根据用户行为动态调整推荐。
-
情景模拟:展示不同市场情况下产品收益概率分布。
-
跨设备同步:鸿蒙分布式能力同步测评与推荐至平板/智慧屏。
技术趋势与挑战
-
趋势:理财推荐与用户画像深度融合,实时风险监控。
-
挑战:合规要求严格,需可解释推荐逻辑与数据隐私保护。
总结
本文基于鸿蒙系统实现理财产品推荐功能,涵盖风险测评问卷、等级计算、产品匹配与 UI 展示,数据库与服务代码完整可运行,支持动态测评与精准推荐,为鸿蒙金融应用提供可靠的技术基础。
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)