【问题标题】:Generate a Dataframe that follow a mathematical function for each column / row为每列/行生成遵循数学函数的数据框
【发布时间】:2019-10-15 22:38:41
【问题描述】:

有没有办法从头开始创建/生成 Pandas DataFrame,这样每条记录都遵循特定的数学函数?

背景:在金融数学中,非常基本的金融衍生品(例如看涨期权和看跌期权)具有封闭式定价公式(例如 Black Scholes)。这些定价公式可以称为随机函数(因为它们涉及随机项)

我正在尝试创建股票价格的蒙特卡罗模拟(以及随后基于股票价格的期权收益和价格)。比如说,我需要 1000 个路径(行)和 100 个时间步(列)。我想“启动”一个 1000 x 100 并遵循随机方程的数据帧。

# Psuedo-code
MonteCarloDF = DataFrame(rows=1000, columns=100, customFunc=TRUE,
        appliedBy='by column', 
        FUNC={s0=321; 
              s_i=prev*exp(r-q*sqrt(sigma))*T + 
                 (etc)*NormDist(rnd())*sqr(deltaT)}
        )

每行的第 0 列将是 321,随后的每一列将根据上面的FUNC 计算出来。

这是在 VBA 中完成的类似操作的示例

Function MonteCarlo_Vanilla_call(S, K, r, q, vol, T, N)

sum = 0
payoff = 0

For i = 1 To N
 S_T = S * Exp((r - q - 0.5 * vol ^ 2) * T + vol * Sqr(T) * Application.NormSInv(Rnd()))
 payoff = Application.Max(S_T - K, 0)
 sum = sum + payoff
Next i

MonteCarlo_Vanilla_call = Exp(-r * T) * sum / N

End Function

每个传入的变量都是一个常量。 就我而言,我希望同一行中的每一列都与 VBA 代码中的 S_T 一样。这真的是唯一重要的事情。我想应用像 S_T = S * Exp((r - q - 0.5 * vol ^ 2) * T + vol * Sqr(T) * Application.NormSInv(Rnd())) 这样的函数。每个S_T 是同一行中的下一列。有N 列进行了一次模拟。例如,我将进行 1000 次模拟。

321     | 322.125 | 323.277 | ... | column 100 value
321     | 320.704 | 319.839 | ... | column 100 value
321     | 321.471 | 318.456 | ... | column 100 value
...
row 1000| etc     | etc     | ... | value (1000,100)

【问题讨论】:

  • 您尝试了哪些方法以及遇到了哪些具体问题?
  • 自定义函数需要一个先前的值。我不知道该尝试什么,或者从哪里开始。您能否举一个使用同一行中的前一个值的更简单函数的示例?还有其他方法吗?
  • 你能提供一些关于方程中一些变量的上下文吗?或者你有可能有帮助的链接吗?例如,qrsigmaT 这里是什么?
  • 变量将只包含预先定义的常量。我的具体方程式尚未确定,但与images.app.goo.gl/GNRYPawNQv7kwvo5A Black Scholes 类似。

标签: python-3.x pandas user-defined-functions stochastic-process


【解决方案1】:

IIUC,您可以创建自己的函数来生成DataFrame。 在函数内使用.iloc[:, -1] 进行迭代以使用最后创建的列。

我们还将使用numpy.random.randn 生成一个正态分布随机值数组。

您可能需要调整变量的默认值,但想法类似于:

功能

import pandas as pd
import numpy as np
from math import exp, sqrt

def monte_carlo_df(nrows,
                   ncols,
                   col_1_val,
                   r=0.03,
                   q=0.5,
                   sigma=0.002,
                   T=1.0002,
                   deltaT=0.002):
    """Returns stochastic monte carlo DataFrame"""

    # Create first column
    df = pd.DataFrame({'s0': [col_1_val] * nrows})

    # Create subsequent columns
    for i in range(1, ncols):
        df[f's{i}'] = (df.iloc[:, -1] * exp(r - q * sqrt(sigma)) * T
                       + (np.random.randn(nrows) * sqrt(deltaT)))
    return df

使用示例

df = monte_carlo_df(nrows=1000, ncols=100, col_1_val=321)

【讨论】:

  • 这需要一段时间才能理解。非常有趣的是,您计算了每条路径中的下一步,而不是一条路径中的所有步骤。因此,您通过指定randn(nrows) 一次创建一整列,对吗?但是每个随机数仍将来自标准正态分布??地板。
  • 是的,完全正确@VISQL randn(nrows) 将返回一个与DataFrame 中的列形状相同的ndarray。所以它们可以很容易地以数学表达式一起广播
【解决方案2】:

对我来说,您的问题是以下问题的特定版本:Pandas calculations based on other rows。由于您可以旋转,因此我们谈论的是行还是列并不重要。

还有一个与使用列计算有关的问题:Pandas complex calculation based on other columns,它有一个很好的建议,即使用 滚动窗口rolling 函数)或使用shift 函数:Calculate the percentage increase or decrease based on the previous column value of the same row in pandas dataframe

类似计算的速度考虑(或numpy vs pandas 讨论):Numpy, Pandas: what is the fastest way to calculate dataset row value basing on previous N values?

总而言之-您的问题似乎有些重复。

【讨论】:

  • shift 将不起作用,除非您循环 .shift #columns-1 次。