繁体   English   中英

R 到 Python 随机过程转换

[英]R to Python stochastic process translation

我想将下面的 R 代码翻译成 Python。

这主要是一个随机过程,我需要将其转换为 Python。

该代码实现了具有两个波动阶段的跳跃过程的马尔可夫链模拟。

set.seed(42)

nSim   <- 1E5
tau    <- 3
K      <- 105
S0     <- 100
rf     <- 0.05
vol_lo <- 0.25
vol_hi <- 0.75
lambda <- c(3,2) # away-from-lo, away-from-hi

sim_time_in_lo <- function(state0){
  t <- 0
  s <- state0
  time_lo <- 0
  while (t<tau){
    dt <- rexp(n=1,lambda[s])
    if ((t+dt)>tau){ dt <- tau - t}
    if (s==1){time_lo <- time_lo + dt }
    if (s==1){s<-2} else {s <-1}
    t <- t+ dt
  }
  time_lo
}
tau_lo     <- sapply(1:nSim,function(i){sim_time_in_lo(1)})
tau_hi     <- tau - tau_lo
total_var  <- tau_lo * vol_lo^2 + tau_hi * vol_hi^2
drift      <- rf * tau-0.5*total_var
randomness <- sqrt(total_var)*rnorm(nSim,)

Python 尝试如下:

我认为我在 pandas 中使用了像 function 这样的 sapply。

import numpy as np
import pandas as pd


np.random.seed(42)

nSim   = 1000
tau    = 3
K      = 105
S0     = 100
r      = 0.05
vol_lo = 0.25
vol_hi = 0.75
lambd = [3,2] # away-from-lo, away-from-hi

def sim_time_in_lo(state0):
    t = 0
    s = state0
    time_lo = 0
    while (t<tau):
        dt = np.random.exponential(scale = lambd[s],size = nSim)
        if (t+dt)>tau:
            dt = tau - t
        elif s == 1:
                time_lo = time_lo + dt
        elif s == 1:
            s = 2
        else : s = 1
        t = t+ dt
        time_lo

df = pd.DataFrame([sim_time_in_lo(1) for i in range(1,nSim)]);df
tau_hi     = tau - tau_lo
total_var  = tau_lo * vol_lo**2 + tau_hi * vol_hi**2
drift      = r * tau-0.5*total_var
randomness = np.sqrt(total_var)*np.random.normal(size=nSim)

但我收到一个错误

df = pd.DataFrame([sim_time_in_lo(1) for i in range(1,nSim)]);df

ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

我的错误是什么?

您的错误是if (t+dt)>tau dt是一个数组,它使(t+dt)>tau成为 boolean 值的数组。

使用((t+dt)>tau).any()((t+dt)>tau).all()来赋予 if 语句的含义。 .all()表示您希望t+dt的每个值都大于 tau,而.any()表示如果只有一个值更大,这就足够了。

以下是使其运行的一些改进:

nSim = int(1e5)
tau = 3
K = 105
S0 = 100
r = 0.05
vol_lo = 0.25
vol_hi = 0.75
lambd = [3, 2]  # away-from-lo, away-from-hi


def sim_time_in_lo(state0):
    t = 0
    s = state0
    time_lo = 0
    while t < tau:
        dt = np.random.exponential(size=1, scale=1/lambd[s])
        if (t + dt) > tau:
            dt = tau - t
        if s == 0:
            time_lo = time_lo + dt
            s = 1
        else:
            s = 0
        t = t + dt
    if isinstance(time_lo, np.ndarray):
        return time_lo[0]
    return time_lo


tau_lo = np.array([sim_time_in_lo(0) for i in range(nSim)])
tau_hi = tau - tau_lo
total_var = tau_lo * vol_lo ** 2 + tau_hi * vol_hi ** 2
drift = r * tau - 0.5 * total_var
randomness = np.sqrt(total_var) * np.random.normal(size=nSim)
  1. nSim是 1e5,而不是 1000。此语法也适用于 Python,但您需要转换为 int。
  2. Python 使用零索引,与 R 不同,因此状态需要为 0 和 1 才能从lambd获取值。
  3. 指数的size参数应该是 1,返回一个标量,而不是nSim - 这就是你得到错误的原因。
  4. 您必须使用显式return语句,这与 R 不同(否则 Python 函数返回None )。
  5. 修复了一些奇怪的缩进,这也导致了我认为的问题。
  6. time_lo初始化为大小为 1 的数组,否则有时会返回标量。 然后稍后从 size-1 arrays 中提取标量(在列表理解中)
  7. 使用数组代替 Dataframe。
  8. 注意np.random.exponentialscale参数是 $\Beta$,即 $\frac{1}{\lambda}$。 R 的rexprate是 $\lambda$。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM