数据帧与蒙特卡罗模拟计算下一行问题

2024-05-14 20:10:09 发布

您现在位置:Python中文网/ 问答频道 /正文

我想从头开始构建一个数据帧,并基于命名屏障选项之前的值进行计算。我知道我可以用蒙特卡罗模拟来解决这个问题,但它不能按我想要的方式工作

公式是:

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

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

结果应该是,对于每次模拟,它将使用之前的值计算一个新值,对于500天,这意味着S_1应为S_500,总共1000次模拟。(在使用公式之前,我需要根据该值生成新列。) 与此类似: Excel sheet 所以对于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)

我在这里找到了另一个可能的代码,它确实解决了这个问题,但是对于一行,下一行的计算是相同的Generate a Dataframe that follow a mathematical function for each column / row

如果我用公式来代替它,我会遇到同样的问题

替换:

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)

我更可能使用最后一个代码并用它解决问题


Tags: 代码inimportnormdfasnprandom
1条回答
网友
1楼 · 发布于 2024-05-14 20:10:09

在循环并将所有模拟保留在一个列表中时,用新的值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(),这应该避免。(见here

网友
2楼 · 发布于 2024-05-14 20:10:09

基于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)

相关问题 更多 >

    热门问题