使用 Pandas 数据框进行财务建模
Financial modelling with Pandas dataframe
我主要通过Pandas建立了一个简单的DCF模型。基本上所有的计算都发生在一个数据帧中。随着模型变得越来越复杂,模型中添加了更多变量,我想找到一种更好的编码风格。下面的例子可以说明我目前的编码风格——简单明了。
# some customized formulas
def GrowthRate():
def BoundedVal()
....
# some operations
df['EBIT'] = df['revenue'] - df['costs']
df['NI'] = df['EBIT'] - df['tax'] - df['interests']
df['margin'] = df['NI'] / df['revenue']
我循环遍历所有年份来计算值。现在我在模型中添加了 500 多个变量,计算也变得更加复杂。我正在考虑为每个变量创建一个单独的 def 并相应地更新主 df。所以上面的代码会变成:
def EBIT(t):
df['EBIT'][t] = df['revenue'][t] - df['costs'][t]
#....some more ops
return df['EBIT'][t]
def NI(t):
df['NI'][t] = EBIT(t) - df['tax'][t] - df['interests'][t]
#....some more ops
return df['NI'][t]
def margin(t):
if check_df_is_nan():
df['margin'][t] = NI(t) - df['costs'][t]
#....some more ops
return df['margin'][t]
else:
return df['margin'][t]
每个函数都能够 1) 计算结果并更新 df 2)return 如果被其他函数调用则值。
为避免冗余计算(想想margin(t)是否被多次调用),最好在每个def中添加一个"check if val has been calculated before"函数。
我的问题:1) 是否可以将 if 语句添加到一组 defs 中?类似于上面的 if 子句。
2) 我有超过 50 个自定义 def,所以主文件变得太长了。我不能简单地将所有 def 移动到另一个文件并全部导入,因为一些 def 还引用主文件中的数据框。有什么建议么?我可以将 df 设置为全局变量,以便其他文件中的 def 能够修改和更新吗?
对于 1,只需检查该值是否为 NaN。
import pandas as pd
def EBIT(t):
if pd.notnull(df['EBIT'][t]):
return df['EBIT'][t]
df['EBIT'][t] = df['revenue'][t] - df['costs'][t]
...
对于 2,使用全局变量可能有效,但这是一种糟糕的方法。您真的应该尽可能避免使用它们。
您应该做的是让每个函数都将全局数据框作为参数。然后就可以传入你要操作的数据框了。
# in some other file
def EBIT(df, t):
# logic goes here
# in the main file
import operations as op
# ...
op.EBIT(df, t)
enter code here
P.S。您是否考虑过一次对整个列进行操作而不是使用 t?它应该快得多。
我主要通过Pandas建立了一个简单的DCF模型。基本上所有的计算都发生在一个数据帧中。随着模型变得越来越复杂,模型中添加了更多变量,我想找到一种更好的编码风格。下面的例子可以说明我目前的编码风格——简单明了。
# some customized formulas
def GrowthRate():
def BoundedVal()
....
# some operations
df['EBIT'] = df['revenue'] - df['costs']
df['NI'] = df['EBIT'] - df['tax'] - df['interests']
df['margin'] = df['NI'] / df['revenue']
我循环遍历所有年份来计算值。现在我在模型中添加了 500 多个变量,计算也变得更加复杂。我正在考虑为每个变量创建一个单独的 def 并相应地更新主 df。所以上面的代码会变成:
def EBIT(t):
df['EBIT'][t] = df['revenue'][t] - df['costs'][t]
#....some more ops
return df['EBIT'][t]
def NI(t):
df['NI'][t] = EBIT(t) - df['tax'][t] - df['interests'][t]
#....some more ops
return df['NI'][t]
def margin(t):
if check_df_is_nan():
df['margin'][t] = NI(t) - df['costs'][t]
#....some more ops
return df['margin'][t]
else:
return df['margin'][t]
每个函数都能够 1) 计算结果并更新 df 2)return 如果被其他函数调用则值。
为避免冗余计算(想想margin(t)是否被多次调用),最好在每个def中添加一个"check if val has been calculated before"函数。
我的问题:1) 是否可以将 if 语句添加到一组 defs 中?类似于上面的 if 子句。 2) 我有超过 50 个自定义 def,所以主文件变得太长了。我不能简单地将所有 def 移动到另一个文件并全部导入,因为一些 def 还引用主文件中的数据框。有什么建议么?我可以将 df 设置为全局变量,以便其他文件中的 def 能够修改和更新吗?
对于 1,只需检查该值是否为 NaN。
import pandas as pd
def EBIT(t):
if pd.notnull(df['EBIT'][t]):
return df['EBIT'][t]
df['EBIT'][t] = df['revenue'][t] - df['costs'][t]
...
对于 2,使用全局变量可能有效,但这是一种糟糕的方法。您真的应该尽可能避免使用它们。
您应该做的是让每个函数都将全局数据框作为参数。然后就可以传入你要操作的数据框了。
# in some other file
def EBIT(df, t):
# logic goes here
# in the main file
import operations as op
# ...
op.EBIT(df, t)
enter code here
P.S。您是否考虑过一次对整个列进行操作而不是使用 t?它应该快得多。