Создание симуляции Монте-Карло из петли питона
Я пытаюсь вычислить вероятность цикла for, возвращающего значение ниже 10% от начального значения, используя симуляцию Монте-Карло.
for i in range(0, period):
if i < 1:
r=(rtn_daily[i]+sig_daily[i]*D[i])
stock = stock_initial * (1+r)
elif i >=1:
r=(rtn_daily[i]+sig_daily[i]*D[i])
stock = stock * (1+r)
print(stock)
Это цикл for, который я хочу выполнить большое количество раз (200000 как грубое число) и рассчитать вероятность того, что:
stock < stock_initial * .9
Я нашел примеры, которые определяют их начальный цикл как функцию, а затем будут использовать эту функцию в цикле, поэтому я попытался определить функцию из моего цикла:
def stock_value(period):
for i in range(0, period):
if i < 1:
r=(rtn_daily[i]+sig_daily[i]*D[i])
stock = stock_initial * (1+r)
elif i >=1:
r=(rtn_daily[i]+sig_daily[i]*D[i])
stock = stock * (1+r)
return(stock)
Это дает значения для "акции", которые, кажется, не соответствуют тому же диапазону, что и раньше, будучи определенными как функция.
используя этот код, я попытался запустить симуляцию Монте-Карло:
# code to implement monte-carlo simulation
number_of_loops = 200 # lower number to run quicker
for stock_calc in range(1,period+1):
moneyneeded = 0
for i in range(number_of_loops):
stock=stock_value(stock_calc)
if stock < stock_initial * 0.90:
moneyneeded += 1
#print(stock) this is to check the value of stock being produced.
stock_percentage = float(moneyneeded) / number_of_loops
print(stock_percentage)
но это не дает результатов за пределами 10% -ного диапазона, даже когда оно повторяется 200000 раз, кажется, что диапазон / разброс результатов каким-то образом сильно уменьшается в моей определенной функции.
Может кто-нибудь увидеть проблему в моей определенной функции stock_value или может найти способ реализации симуляции Монте-Карло способом, с которым я не сталкивался?
Мой полный код для справки:
#import all modules required
import numpy as np # using different notation for easier writting
import scipy as sp
import matplotlib.pyplot as plt
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#collect variables provided by the user
stock_initial = float(12000) # can be input for variable price of stock initially.
period = int(63) # can be edited to an input() command for variable periods.
mrgn_dec = .10 # decimal value of 10%, can be manipulated to produce a 10% increase/decrease
addmoremoney = stock_initial*(1-mrgn_dec)
rtn_annual = np.repeat(np.arange(0.00,0.15,0.05), 31)
sig_annual = np.repeat(np.arange(0.01,0.31,0.01), 3) #use .31 as python doesn't include the upper range value.
#functions for variables of daily return and risk.
rtn_daily = float((1/252))*rtn_annual
sig_daily = float((1/(np.sqrt(252))))*sig_annual
D=np.random.normal(size=period) # unsure of range to use for standard distribution
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# returns the final value of stock after 63rd day(possibly?)
def stock_value(period):
for i in range(0, period):
if i < 1:
r=(rtn_daily[i]+sig_daily[i]*D[i])
stock = stock_initial * (1+r)
elif i >=1:
r=(rtn_daily[i]+sig_daily[i]*D[i])
stock = stock * (1+r)
return(stock)
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# code to implement monte-carlo simulation
number_of_loops = 20000
for stock_calc in range(1,period+1):
moneyneeded = 0
for i in range(number_of_loops):
stock=stock_value(stock_calc)
if stock < stock_initial * 0.90:
moneyneeded += 1
print(stock)
stock_percentage = float(moneyneeded) / number_of_loops
print(stock_percentage)
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1 ответ
Публикация ответа, так как у меня нет точек для комментариев. Некоторые вопросы о вашем коде - прохождение этих может помочь вам найти ответ:
Почему вы определили
rtn_annual
как массив,np.repeat(np.arange(0.00,0.15,0.05), 31)
? Так как он просто повторяет значения[0.0, 0.05, 0.1]
почему бы не определить его как функцию?def rtn_annual(i): vals = [0.0, 0.05, 0.1] return vals[i % 3]
Аналогично для
sig_annual
,rtn_daily
, а такжеsig_daily
- все это - прямые функции индекса, поэтому я не уверен, какое преимущество может дать их создание массивов.Что значит
D
на самом деле представляют? Как вы уже определили, это случайная величина со средним0.0
и стандартное отклонение1.0
, Таким образом, около 95% значений вD
будет в диапазоне (-2,0, +2,0) - это то, что вы ожидаете?Вы проверили свой
stock_value()
работать даже в небольшие периоды (например, от 0 до нескольких дней), чтобы убедиться, что он делает то, что, как вы думаете, должен? Из вашего вопроса неясно, подтвердили ли вы, что когда-либо поступали правильно, для любого ввода и вашего комментария "...(possibly?)
"звучит не очень уверенно.Оповещение спойлера - это почти наверняка нет. В функции
stock_value
Ваше заявление о возврате находится в пределахfor
петля. Это будет выполнено в первый раз, когдаi = 0
и цикл никогда не будет дальше. Это будет основной причиной, по которой функция дает разные результаты в цикле.Кроме того, когда вы говорите, "возвращая значение меньше, чем 10% от...", я предполагаю, что вы имеете в виду "возвращать значение, по крайней мере, на 10% ниже, чем...", так как это ваша вероятность
stock < stock_initial * .9
рассчитывает.
Надеюсь, это поможет. Возможно, вы захотите пройтись по своему коду с помощью отладчика в предпочитаемой вами IDE (idle
, или же thonny
, или же eclipse
(что бы это ни было), чтобы увидеть, что на самом деле делает ваш код.