Dataframe with Monte Carlo Simulation calculation next row 问题

Dataframe with Monte Carlo Simulation calculation next row Problem

我想从头开始构建一个 Dataframe,并根据 Value before named Barrier 选项进行计算。我知道我可以使用 Monte Carlo 模拟来解决它,但它不会按照我想要的方式工作。

公式为:

Value in row before * np.exp((r-sigma**2/2)*T/TradingDays+sigma*np.sqrt(T/TradingDays)*z)

我写的第一个代码只是计算第一列。我知道我需要第二个循环但无法真正管理它。

结果应该是,对于每次模拟,它将使用之前的值计算一个新值,对于 500 天,意味着 S_1 应该是 S_500,总共 1000 次模拟。 (在使用公式之前,我需要根据值生成新列。) 与此类似: 所以对于 1.模拟 500 天,2.模拟 500 天等等...

import numpy as np
import pandas as pd
from scipy.stats import norm
import random as rd
import math 

simulation = 0
S_0 = 42
T = 2
r = 0.02
sigma = 0.20
TradingDays = 500

df = pd.DataFrame()

for i in range (0,TradingDays):
    z = norm.ppf(rd.random())
    simulation = simulation + 1

    S_1 = S_0*np.exp((r-sigma**2/2)*T/TradingDays+sigma*np.sqrt(T/TradingDays)*z)


    df = df.append ({

                    'S_1':S_1,    
                    'S_0':S_0

                     }, ignore_index=True)

    df = df.round  ({'Z':6,
                     'S_T':2
                     })
    df.index += 1
    df.index.name = 'Simulation'


print(df)

我在此处找到了另一个可能的代码,它确实解决了问题,但仅针对一行,下一行只是相同的计算。

如果我只是用我的公式替换它,我会遇到同样的问题。

正在替换:

exp(r - q * sqrt(sigma))*T+ (np.random.randn(nrows) * sqrt(deltaT)))

与:

exp((r-sigma**2/2)*T/nrows+sigma*np.sqrt(T/nrows)*z))
import numpy as np
import pandas as pd
from scipy.stats import norm
import random as rd
import math 

S_0 = 42
T = 2
r = 0.02
sigma = 0.20
TradingDays = 50
Simulation = 100

df = pd.DataFrame({'s0': [S_0] * Simulation})

for i in range(1, TradingDays):
    z = norm.ppf(rd.random())

    df[f's{i}'] = df.iloc[:, -1] * np.exp((r-sigma**2/2)*T/TradingDays+sigma*np.sqrt(T/TradingDays)*z)

print(df)

我会更有可能使用最后的代码并用它解决问题。

在循环并将所有模拟保存在列表中时,用 S_1 的新值覆盖 S_0 的值怎么样? 像这样:

import numpy as np
import pandas as pd
import random
from scipy.stats import norm


S_0 = 42
T = 2
r = 0.02
sigma = 0.20
trading_days = 50
output = []

for i in range(trading_days):
    z = norm.ppf(random.random())
    value = S_0*np.exp((r - sigma**2 / 2) * T / trading_days + sigma * np.sqrt(T/trading_days) * z)
    output.append(value)
    S_0 = value

df = pd.DataFrame({'simulation': output})

也许我遗漏了什么,但我认为不需要第二个循环。

此外,这消除了在循环中调用 df.append(),这应该避免。 (参见

根据bartaelterman的回答解决,非常感谢!

import numpy as np
import pandas as pd
from scipy.stats import norm
import random as rd
import math 


#Dividing the list in chunks to later append it to the dataframe in the right order
def chunk_list(lst, chunk_size):
    for i in range(0, len(lst), chunk_size):
        yield lst[i:i + chunk_size]

def blackscholes():
    d1 = ((math.log(S_0/K)+(r+sigma**2/2)*T)/(sigma*np.sqrt(2)))
    d2 = ((math.log(S_0/K)+(r-sigma**2/2)*T)/(sigma*np.sqrt(2)))
    preis_call_option = S_0*norm.cdf(d1)-K*np.exp(-r*T)*norm.cdf(d2)
    return preis_call_option


K = 40
S_0 = 42
T = 2
r = 0.02
sigma = 0.2
U = 38
simulation = 10000
trading_days = 500
trading_days = trading_days -1

#creating 2 lists for the first and second loop
loop_simulation = []
loop_trading_days = []


#first loop calculates the first column in a list
for j in range (0,simulation):
    print("Progressbar_1_2 {:2.2%}".format(j / simulation), end="\n\r")
    S_Tag_new = 0
    NORM_S_INV = norm.ppf(rd.random())
    S_Tag = S_0*np.exp((r-sigma**2/2)*T/trading_days+sigma*np.sqrt(T/trading_days)*NORM_S_INV)
    S_Tag_new = S_Tag
    loop_simulation.append(S_Tag)




#second loop calculates the the rows for the columns in a list
    for i in range (0,trading_days):
        NORM_S_INV = norm.ppf(rd.random())
        S_Tag = S_Tag_new*np.exp((r-sigma**2/2)*T/trading_days+sigma*np.sqrt(T/trading_days)*NORM_S_INV)
        loop_trading_days.append(S_Tag)
        S_Tag_new = S_Tag 

#values from the second loop will be divided in number of Trading days per Simulation           
loop_trading_days_chunked = list(chunk_list(loop_trading_days,trading_days))

#First dataframe with just the first results from the firstloop for each simulation
df1 = pd.DataFrame({'S_Tag 1': loop_simulation})

#Appending the the chunked list from the second loop to a second dataframe
df2 = pd.DataFrame(loop_trading_days_chunked)

#Merging both dataframe into one
df3 = pd.concat([df1, df2], axis=1)