使用Google OR-Tools分析过去20年中国金融资产最佳配置组合
前两天,在朋友圈里看到一张截至2022年Q2的金融资产历年收益图如下,图中列举了国内从2005年到2022年近20年主要的金融资产历年收益率,随产生想法分析和验证下面几个问题:
- 过去20年,基于怎样的资产配置才能让收益最大化?
- 如果完全拒绝风险,是否可以理财,收益率会是多少?
- 是否有风险小,收益高的资产配置组合?
- 抛开择时和运气,资产配置的最佳持有时长是多少年?
分析方法
使用工具:Google OR-Tools,OR-Tools是谷歌用于组合优化的软件工具,可以从大量可能的解决方案中找到问题的最佳解决方案。比如本例中,假如2005年初我手上有100元钱,怎么把这100元钱分到不同的金融资产上有太多方案。但基本上只会有一种组合让最终收益最大化,也基本只会有一种组合让每年本金不出现亏损的前提下实现收益尽可能最大化。这些都会借助于这个工具进行分析和验证。
一些计算条件:
- 由于图中的信托和房地产门槛比较高,不适于一般理财者,所以刨除掉。只保留银行理财、货币基金、债卷基金、股票基金、股票等5种金融资产。
- 假定只是2005年初投入100元本金,中间不增加本金,也不减少账户资金。
- 投资组合是固定的,比如银行理财占比x%,股票占比y%等,这个比例会保持不变。每年年初会基于上一年剩余本金进行比例的动态平衡调整,调整的目的是让投资组合依然保持这个比例。
- 无风险是相对于每年年初的剩余资金。举例:2005年初投入100元,那么2005年末剩余资金必须大于等于100元。如果2005年获得了10元收益也就是说2006年年初的账户资金是110元(100元本金+10元收益),那么2006年末剩余资金必须大于等于年初资金110元。
分析结果
最终的分析结果如下图:
具体分析内容请参考文章
代码
//定义单年最大允许亏损比例。(比如:0.2代表单年最大允许亏损比例为20%;1代表无限制;0代表不允许亏损)
float allowableMaximumLossRatio = 1f; //无限制
//float allowableMaximumLossRatio = 0.2f; //单年最大允许亏损比例为20%
//float allowableMaximumLossRatio = 0f; //不允许亏损
//待处理数据,此处全部转换为整数处理
(String year, long[] values)[] data = new[]
{
("2005", new long[]{ 10273, 10236, 10912, 10140, 8848}),
("2006", new long[]{ 10280, 10150, 11494, 22263, 21190}),
("2007", new long[]{ 10360, 10336, 11822, 22833, 26621}),
("2008", new long[]{ 11542, 10356, 10646, 4858, 3708}),
("2009", new long[]{ 10425, 10142, 10504, 17117, 20547}),
("2010", new long[]{ 10392, 10181, 10690, 9972, 9312}),
("2011", new long[]{ 10463, 10355, 9711, 7547, 7759}),
("2012", new long[]{ 10588, 10397, 10622, 10545, 10468}),
("2013", new long[]{ 10482,10395,10061,11013,10544}),
("2014", new long[]{ 10597,10460,11848,12939,15244}),
("2015", new long[]{ 10556,10362,10993,13467,13850}),
("2016", new long[]{ 10471,10261,9965,8969,8709}),
("2017", new long[]{ 10422,10384,10165,11063,10493}),
("2018", new long[]{ 10496,10375,10543,7683,7175}),
("2019", new long[]{ 10446,10266,10422,14109,13302}),
("2020", new long[]{ 10414,10213,10315,14454,12343}),
("2021", new long[]{ 10310, 10228, 10393, 10587, 10917}),
("2022", new long[]{ 10350, 10101, 10090, 8928, 9047}),
};
// 创建CP模型.
CpModel model = new CpModel();
//定义变量:各类资产配置比例
IntVar a = model.NewIntVar(0, 100, "a"); //银行理财
IntVar b = model.NewIntVar(0, 100, "b"); //货币基金
IntVar c = model.NewIntVar(0, 100, "c"); //债卷基金
IntVar d = model.NewIntVar(0, 100, "d"); //股票基金
IntVar e = model.NewIntVar(0, 100, "e"); //股票
//创建约束条件:配置比例总和为100%
model.Add(a + b + c + d + e <= 100);
model.Add(a + b + c + d + e >= 100);
//创建约束条件:限定低风险配置比例
//model.Add(a >= 40);
//model.Add(d + e <= 40);
//定义变量数组:单年年末资金
IntVar[] yearResults = new IntVar[data.Length];
//定义变量数组:单年收益率
IntVar[] yearRatios = new IntVar[data.Length];
for (int i = 0; i<data.Length; i++)
{
var yearItem = data[i];
//定义变量:当前年度收益率
IntVar ratio = model.NewIntVar(0, 100 * 10000 * 3, $"ratio{i}");
model.Add(ratio == a * yearItem.values[0] + b * yearItem.values[1] + c * yearItem.values[2] + d * yearItem.values[3] + e * yearItem.values[4]);
yearRatios[i] = ratio;
//创建约束条件:单年最大允许亏损比例
model.Add(ratio >= Convert.ToInt32(100 * (1 - allowableMaximumLossRatio)) * 10000);
//定义变量:当前年末资金
IntVar resultA = model.NewIntVar(0, 100 * 100 * 10000 * Convert.ToInt64(Math.Pow(3, i+1)), $"resultA{i}");
model.AddMultiplicationEquality(resultA, i==0? model.NewConstant(100) : yearResults[i-1], ratio);
//定义变量:由于原生数据的收益率和配置比例是使用转换后的整数计算的,所以这里使用当前年末资金除以100*10000
IntVar result = model.NewIntVar(0, 100 * Convert.ToInt64(Math.Pow(3, i+1)), $"result{i}");
model.AddDivisionEquality(result, resultA, model.NewConstant(100 * 10000));
yearResults[i] = result;
}
//设定求解目标为最终资金最大
model.Maximize(yearResults[data.Length -1]);
//求解
CpSolver solver = new CpSolver();
CpSolverStatus status = solver.Solve(model);
//输出求解结果
if (status == CpSolverStatus.Optimal || status == CpSolverStatus.Feasible)
{
Console.WriteLine("银行理财配置比: " + solver.Value(a)+"%");
Console.WriteLine("货币基金配置比: " + solver.Value(b)+"%");
Console.WriteLine("债卷基金配置比: " + solver.Value(c)+"%");
Console.WriteLine("股票基金配置比: " + solver.Value(d)+"%");
Console.WriteLine("股票配置比: " + solver.Value(e)+"%");
for (int i = 0; i<data.Length; i++)
{
Console.WriteLine($"{data[i].year} 年末资金:{solver.Value(yearResults[i])} 收益率:{String.Format("{0:P}", solver.Value(yearRatios[i]) / 1000000.00 - 1)}");
}
Console.WriteLine($"最终资金: {solver.ObjectiveValue}");
Console.WriteLine($"年化收益率: {String.Format("{0:P}", Math.Pow((solver.ObjectiveValue - 100)/100, 1.00/data.Length)-1)}");
}
else
{
Console.WriteLine("求解失败,未找到合适结果.");
}
Console.WriteLine($"求解耗时: {solver.WallTime()}s");
Github地址:代码
使用Google OR-Tools分析过去20年中国金融资产最佳配置组合的更多相关文章
- Google PageSpeed Tools 性能测试分析
今天给大家介绍下一个工具:Google PageSpeed Tools,根据官方的介绍,简单梳理如下: Page Speed Insights能针对移动设备和电脑设备衡量网页的性能.该工具会抓取网址两 ...
- Google performance Tools (gperftools) 使用心得
Google performance Tools (gperftools) 使用心得 gperftools是google开发的一款非常实用的工具集,主要包括:性能优异的malloc free内存分配器 ...
- Google Optimization Tools实现加工车间任务规划【Python版】
上一篇介绍了<使用.NET Core与Google Optimization Tools实现加工车间任务规划>,这次将Google官方文档python实现的版本的完整源码献出来,以满足喜爱 ...
- 使用.NET Core与Google Optimization Tools实现加工车间任务规划
前一篇文章<使用.NET Core与Google Optimization Tools实现员工排班计划Scheduling>算是一种针对内容的规划,而针对时间顺序任务规划,加工车间的工活儿 ...
- Google Optimization Tools实现员工排班计划Scheduling【Python版】
上一篇介绍了<使用.Net Core与Google Optimization Tools实现员工排班计划Scheduling>,这次将Google官方文档python实现的版本的完整源码献 ...
- 使用.NET Core与Google Optimization Tools实现员工排班计划Scheduling
上一篇说完<Google Optimization Tools介绍>,让大家初步了解了Google Optimization Tools是一款约束求解(CP)的高效套件.那么我们用.NET ...
- Google Optimization Tools介绍
Google Optimization Tools(OR-Tools)是一款专门快速而便携地解决组合优化问题的套件.它包含了: 约束编程求解器. 简单而统一的接口,用于多种线性规划和混合整数规划求解, ...
- Android Launcher分析和修改1——Launcher默认界面配置(default_workspace)
最近工作都在修改Launcher,所以打算把分析源码和修改源码的过程记录下来,最近会写一些关于Launcher的分析和修改博文.因为我是修改4.0.3的Launcher,所以后面文章里面的Launch ...
- 外国人专门写了一篇文章,来分析为什么go在中国如此火
外国人专门写了一篇文章,来分析为什么go在中国如此火: <Why is Golang popular in China?> http://herman.asia/why-is-go-pop ...
- mysql 5.7.20解压版安装配置
MySql 5.7.20版本免安装版配置过程 下载地址为: https://dev.mysql.com/downloads/mysql/ 最下面根据自己的操作系统选择合适的型号 下载完以后解压缩到 ...
随机推荐
- 使用 Elastic Stack 分析地理空间数据 (二)
文章转载自:https://blog.csdn.net/UbuntuTouch/article/details/106546064 在之前的文章 "Observability:使用 Elas ...
- 微软出品自动化神器Playwright(Playwright+Java)系列(四) 之 浏览器操作
写在前面 今天是国庆节的最后一天,明天又要上班了,真的是感觉好像才开始放假一样,还是因为失恋没缓过来吗? 我的国庆七天 第1天,当了近半天的司机,陪家人去各大超市去购物,下午在家躺····· 第2-5 ...
- P3998 [SHOI2013]发微博 方法记录
原题链接 [SHOI2013]发微博 题目描述 刚开通的 SH 微博共有 \(n\) 个用户(\(1\sim n\) 标号),在这短短一个月的时间内,用户们活动频繁,共有 \(m\) 条按时间顺序的记 ...
- 基于纯前端类Excel表格控件实现在线损益表应用
财务报表也称对外会计报表,是会计主体对外提供的反映企业或预算单位一定时期资金.利润状况的会计报表,由资产负债表.损益表.现金流量表或财务状况变动表.附表和附注构成.财务报表是财务报告的主要部分,不包括 ...
- rowkey设计原则和方法
rowkey设计首先应当遵循三大原则: 1.rowkey长度原则 rowkey是一个二进制码流,可以为任意字符串,最大长度为64kb,实际应用中一般为10-100bytes,它以byte[]形式保存, ...
- 2022-08-21-Freewind主题_cdn替换版
layout: post cid: 16 title: Freewind主题 cdn替换版 slug: 16 date: 2022/08/21 14:06:00 updated: 2022/08/21 ...
- 通过openlayers加载dwg格式的CAD图并与互联网地图叠加
Openlayers介绍 Openlayers是一个基于Javacript开发,免费.开源的前端地图开发库,使用它,可以很容易的开发出WebGIS系统.目前Openlayers支持地图瓦片.矢量数 ...
- 网页计时访问器application对象
网页计时访问器 application对象代表Web应用本身,整个Web共享一个application对象.开始于服务器打开结束与服务器关闭.在不同的浏览器打开j计时器仍然有作用.除非把服务器关闭 & ...
- 齐博x1如果把万能表单直接插入到内容中去
很多时候,你创建了一个万能表单可能像下面这个情况,在文章中加一个链接叫别人点击填表,其实这个很不人性化,用户也容易忽略. 其实你完全可以像下面这样,把表单直接引用到文章中来.给用户更直观的感觉 那是如 ...
- 齐博x1如何取消禁止跨城市密码登录限制
为安全起意见,只要用户绑定了手机,或者QQ登录,或者微信登录其中的一项,只要用户的IP所在城市变了,就会禁止密码登录.如下图所示 而必须选择绑定过的手机或QQ或微信其中一种方式登录.以避免密码被盗所带 ...