金融数值计算系列:1现金流折现模型

贾药停先生在PPT上版出“让我们一起,为梦想窒息”的宣言之后,我开始羞于做任何鼓励或者鸡汤方面的事情,但是我还是要硬着头皮说,如果年少的你想在金融行业拿到体面的收入,而不是每天穿着廉价西装去拉客户,你需要学习金融数值计算。

从本贴起,小僧开始发布金融数值计算系列tutorial,目的有二,第一,帮助对这个领域感兴趣的同学从零开始学习;第二,利用这个平台来做code review和收集feedback,希望有朝一日能够将这些code编汇成书。小僧的初步构想是利用Julia的强大numerical computing能力,展现其在portfolio optimization和derivative pricing方面的应用。

理论部分来自于互联网,浅显易懂是首要标准,感兴趣的同学可以读更深一点的教材。

##########################################################################

现金流折现模型 (英语: D iscounted C ashflow M odel,缩写DCF ),是公司财务和投资学领域应用最广泛的定价模型之一,在学术和实践领域都发挥着巨大的作用。

现金流折现模型的公式可以表述如下:

P0 = (E0CF1)/(1 + r) + (E0CF2)/(1 + r)2 + … (延续到无限期)

其中P0代表某一企业、资产或工程的现值(当前价值),E0CFn代表当前预测的未来第n期产生的自由现金流,r代表自由现金流的折现率,即资本成本。这一模型的涵义是:一项投资或一个企业的当前价值,等于其未来所产生的现金流的现值之和。

##########################################################################
以下code是一个最简单的非连续现金流折现模型,可以写出C++/Python的for loop风格,也可以写出Matlab的vectorization的风格。

function cash_flow_pv_discrete(cflow_times, cflow_amounts, r)
    PV = 0.0 
    for t in 1:length(cflow_times) 
    PV += cflow_amounts[t]/(1.0+r)^cflow_times[t] 
    end
    return PV 
end




cflow_amounts_examp = [-100 75 75]
cflow_times_examp = [0 1 2]
r_examp = 0.1

ans1 = cash_flow_pv_discrete(cflow_times_examp, cflow_amounts_examp, r_examp)
ans2 = cflow_amounts_examp * (1/(1+r_examp)).^cflow_times_examp'
2 个赞

目前增加了MathJax插件的,公式可以用$$渲染。

然后,代码用```套起来可以增加高亮(虽然对Julia支持得不是特别好)

Julian的风格是函数一般最后不写 return。return只是跳转。

大部分这方面的教材都是用c++写的,所以我写成这样方便读者横向对比

@inbounds for t in eachindex(cflow_times) 
    PV += cflow_amounts[t]/(1.0+r)^cflow_times[t]
end

速度应该更接近C++. Julia有默认的bounds check, 但是C++没有.

可以在运行的时候用编译指令去掉bounds check

没有谁说过不写return是Julia的风格吧?performance: mark REPL and Doc code as non-specializeable by vtjnash · Pull Request #28065 · JuliaLang/julia · GitHub

Implicit return is bad for compiler performance (and sometimes runtime performance)…

1 个赞

+1 感觉这只是一种 code-style,无论显式还是隐式,return 的坑貌似只有这个:

julia> function foo()
         return x::Int = 3.0
       end
foo (generic function with 1 method)

julia> foo()
3.0

嗯,顺便一提,对于返回值我习惯这样写约束

julia> function foo(k)::Int
           k > 0 ? 3.0 : 1//1
       end
foo (generic function with 1 method)

julia> foo(1)
3

julia> foo(-1)
1

这样就不管在哪里返回都可以保证是Int了。

:sweat_smile:理论讲得太学院了