结合实际问题浅谈如何使用蒙特卡罗算法模拟投资分析
在金融行业中,几乎所有银行都会做投资前的市场调查工作,分析历史数据.然后将这些汇总信息提供给高级项目专员作最后的决定工作.有些银行会首先采用计算机分析模拟,之后再将结果与个人经验相结合来做最后的决定.
在保证算法和历史数据正确的前提下我们使用计算机模拟主要有以下优点:
1.给最终决策者一个可信的经验数据做参考
2.计算机可以不知疲倦地分析海量信息.并且可以应用多种复杂的模拟算法同时验证
3.算法一般由多人开发,常用算法经过多家公司实践,分析方法较为可靠.
4.最大程序上避免了由个人或团队凭经验决策而出现的投资误判.
实例:
我们要投资1000万给某个项目.该项目预期年销售收入670万元,年销售税金15万元,年经营成本390万元.年折旧费65万元.以项目的投资利润作为项目的考核指标.而项目的年销售收入和年经营成本为不确定因素.我们期望利润率在15%以上.
通过上面的描述可知:
经验利润率 = 年利润率总额/投资总额 = (670-15-390-65)/1000 = 20%
依据经验可知如果该项目利润率大于15%,则该项目具有可行性.但是事实可能跟我们想的不一样,所以就需要做风险分析.
在金融风险分析中,敏感度分析是常用的手段之一.
敏感度分析是指从众多不确定性因素中找出对投资项目经济效益指标有重要影响的敏感性因素,并分析、预测其对项目经济效益指标的影响程度和敏感性程度.进而判断项目承受风险能力的一种不确定性分析方法.
建模:
使用蒙特卡罗模拟算法对该项目建模
【蒙特卡罗模拟算法】
蒙特卡罗方法(Monte Carlo method)是以概率和统计的理论、方法为基础的一类随机方法,将所求解的问题同一定的概率模型相联系,用电子计算机实现统计模拟或抽样,以获得问题的近似解。
该算法被广泛应用于不同的领域,包括生物科学,机械制造以及金融计算.
该算法创造了一种假设的未来,它是通过产生数以万计甚至百万计的样本结果并分析他们的共性实现.在金融领域中,蒙特卡罗模拟算法被用于风险分析,风险鉴定等.
1.确定要解决的问题是否可以用概率统计的方法解决
投资项目中有2个不确定因素:销售输入和经营成本
在可预见的时间内,项目的不确定因素在-10%到+10%波动(这是一个经验值,一般可通过产品销售的历史信息获得,也可由销售团队指定)
该项目预期年销售收入670万元,年销售税金15万元,年经营成本390万元.年折旧费65万元.以项目的投资利润作为项目的考核指标.而项目的年销售收入和年经营成本为不确定因素.我们期望利润率在15%以上.
项目经验利润率 = 年利润率总额/投资总额 = (销售输入-经营成本-销售税金-折扣费)/1000 = 20%
2.确定随即采样点的计算方法
a.只有一个不确定因素变化时
当销售输入变化时,投资收益率=[670*(1+变化幅度)-15-390-65]/1000
当经营成本变化时,投资收益率=[670-15-390*(1+变化幅度)-65]/1000
b.两个不确定因素同时变化时
当销售输入和经营成本同时变化时
投资收益率=[670*(1+变化幅度)-15-390*(1+变化幅度)-65]/1000
3.确定随即采样点的选择算法
当采样点确定的收益率大于15%时,则选择该点作为有效点
4.根据比值确定最终结果
收益率大于15%的采样点数量与全部采样点的数量之比为该项目投资达到收益率的概率
代码实现
我们已经使用建模已经蒙特卡罗模拟算法对问题进行了建模,接下来使用Java实现
import java.util.Random; /** * * RiskAnalysis.java * * @version : 1.1 * * @author : 苏若年 <a href="mailto:DennisIT@163.com">发送邮件</a> * * @since : 1.0 创建时间: 2013-3-22 上午10:39:56 * * TODO : class RiskAnalysis.java is used for ... * */ public class RiskAnalysis { static Random incomeGen = new Random(); static Random costGen = new Random(); //项目年销售收入预期为670万元 final static double INCOME = 670; //年经营成本预期为390万元 final static double COST = 390; //年销售税金15万元 final static double DUTY = 15; //年折旧费65万元 final static double DEPRECIATION = 65; //波动范围 final static double MIN = 0.9; final static double MAX = 1.1; public static double getRandomInCome(){ //变化幅度为0.9~1.1 //Min + (Random.nextDouble()*(Max-Min)) return INCOME*(MIN + (incomeGen.nextDouble()*(MAX-MIN))); }
public static double getRandomCost(){ //变化幅度为0.9~1.1 //Min + (Random.nextDouble()*(Max-Min)) return COST*(MIN + (costGen.nextDouble()*(MAX-MIN))); }
public static double getRateOnlyIncomeChange(long evaluationNum,double expectRate,double investMent){ long evaluationTime = 0; long expected = 0; //当销售输入变化是,投资收益率=[670*(1+变化幅度)-15-390-65]/1000 while(evaluationTime<evaluationNum){ double randIncome = getRandomInCome(); double rate = (randIncome-DUTY-COST-DEPRECIATION)/investMent; evaluationTime++; if(rate>=expectRate){ expected++; } } return (double)expected/evaluationTime; }
public static double getRateOnlyCostChange(long evaluationNum,double expectRate,double investMent){ long evaluationTime = 0; long expected = 0; //当经营成本变化时,投资收益率=[670-15-390*(1+变化幅度)-65]/1000 while(evaluationTime<evaluationNum){ double randCost = getRandomCost(); double rate = (INCOME-DUTY-randCost-DEPRECIATION)/investMent; evaluationTime++; if(rate>=expectRate){ expected++; } } return (double)expected/evaluationTime; }
public static double getRateBothIncomeCostChange(long evaluationNum,double expectRate,double investMent){ //当销售输入与经营成本同时变化时,投资收益率=[670*(1+变化幅度)-15-390*(1+变化幅度)-65]/1000 long evaluationTime = 0; long expected = 0; while(evaluationTime < evaluationNum){ double randIncom = getRandomInCome(); double randCost = getRandomCost(); double rate = (randIncom-DUTY-randCost-DEPRECIATION)/investMent; evaluationTime++; if(rate>=expectRate){ expected++; } } return (double)expected/evaluationTime; }
public static void main(String[] args) { //投资1000万元 double investMent = 1000; //预期收益率 double expectRate = 0.15; //采样次数 long evaluationNum = 10000; System.out.println("当销售输入变化时,预期收益率 > "+ expectRate +"的概率为:" +getRateOnlyIncomeChange(evaluationNum, expectRate, investMent)); System.out.println("当经营成本变化时,预期收益率 > " + expectRate +"的概率为:" + getRateOnlyCostChange(evaluationNum, expectRate, investMent)); System.out.println("当经营成本和收入都发生波动时,预期收益率 > "+expectRate+"的概率为:"+ getRateBothIncomeCostChange(evaluationNum, expectRate, investMent)); }
}
运行结果:
当销售输入变化时,预期收益率 > 0.15的概率为:0.8678 当经营成本变化时,预期收益率 > 0.15的概率为:1.0 当经营成本和收入都发生波动时,预期收益率 > 0.15的概率为:0.8526
对于该实例,收益和支出的”变化幅度”将影响最终的计算结果
1.改变变化率
将变化幅度从-10% ~ +10%,变化为-20% ~ +20%,得到如下结果
当销售输入变化时,预期收益率 > 0.15的概率为:0.6873 当经营成本变化时,预期收益率 > 0.15的概率为:0.8214 当经营成本和收入都发生波动时,预期收益率 > 0.15的概率为:0.6855
通过增大变化幅度,可以看到,当销售输入有大的变化时,其预期收益率高于我们期望值的概率(0.6873),比经营成本与销售收入同时发生波动的收益率(0.6855)高,而如果销售输入大幅度变化下,同时对成本调节并保持原变化率不变,预期收益率会向好的方向发展.
但是修改变化率的情况下,运行的结果并不一致.即上面的分析其实并不是很准确的模拟出最终结果.蒙特卡罗算法的精确度随着采样次数的增加而增加.所以可以改变采样次数
2.改变采样次数
我们实例中的采样次数为10000次,现在我们分别改到100000,1000000次,然后再来分析结果.
下面的运行结果是波动范围在-20% ~ +20%,采样次数为10000000L的某一次运行结果
当销售输入变化时,预期收益率 > 0.15的概率为:0.6867322 当经营成本变化时,预期收益率 > 0.15的概率为:0.8204112 当经营成本和收入都发生波动时,预期收益率 > 0.15的概率为:0.6864553
3.另一种提高精确度的做法就是多次求解取平均值,或者再次不确定结果重新使用蒙特卡罗算法分析概率.不管哪种方法都需要大量的计算,得到精确结果的代价是求解速度的降低.
我们测重点不是如何去提高该实例分析的精度,重点是学习如何使用蒙特卡罗模拟算法进行数据模拟解决实际问题.
实例出处:[云计算应用开发实践]
转载请注明出处:[http://www.cnblogs.com/dennisit/archive/2013/03/22/2975294.html]