I have made a simulator using Python for a game called Final Fantasy XII. The purpose of this simulator is to see how much "gil" (in-game currency) you can get from one particular enemy.
This should output around 23000 from our experiance, but what happens with this is, it outputs 24000 usually, but sometimes 29000. Considering it takes 1000 samples, it is impossible for that to be coincident. I think this code has problems with random generator, but I have no idea.
Are there reasons python simulator sometimes goes wrong?
import random
# defining variables, dictionaries and functions here
for t in range (1, test + 1):
for n in range (1, dustia + 1):
c = c + 1 # first, increase the chain counter
r = random.random()
# deciding a thing using "if r < [probability]" here
# ....
# apparently this part caused the problem
r = random.random()
if m == 1 and r < 0.4:
m = 0
elif m == 0 and r < 0.05:
m = 1
r1 = random.random() # RNG for book
r2 = random.random() # RNG for staff
rr1 = random.random() # amount of books
rr2 = random.random() # amount of staff
# deciding another thing using r < [probability] here
#summing up samples and calculating average here
Related
We have a barrier call option of European type with strike price K>0 and a barrier value
0 < b< S0 ,
where S_0 is the starting price.According to the contract, the times 0<t_1<...<t_k<T the price must be checked S(t_k)>b for every k.
Assuming the S(t) is described with the binomial option model with u=1.1 and d = 0.9,r=0.05,T=10, and t_1=2,t_2=4 and t-3=7 the times that the asset must be checked.Also consider the S_0=100,K=125 and the barrier b=60.
My attempt is the following :
# Initialise parameters
S0 = 100 # initial stock price
K = 125 # strike price
T = 10 # time to maturity in years
b = 60 # up-and-out barrier price/value
r = 0.05 # annual risk-free rate
N = 4 # number of time steps
u = 1.1 # up-factor in binomial models
d = 0.9 # ensure recombining tree
opttype = 'C' # Option Type 'C' or 'P'
def barrier_binomial(K,T,S0,b,r,N,u,d,opttype='C'):
#precompute values
dt = T/N
q = (1+r - d)/(u-d)
disc = np.exp(-r*dt)
# initialise asset prices at maturity
S = S0 * d**(np.arange(N,-1,-1)) * u**(np.arange(0,N+1,1))
# option payoff
if opttype == 'C':
C = np.maximum( S - K, 0 )
else:
C = np.maximum( K - S, 0 )
# check terminal condition payoff
C[S >= b] = 0
# backward recursion through the tree
for i in np.arange(N-1,-1,-1):
S = S0 * d**(np.arange(i,-1,-1)) * u**(np.arange(0,i+1,1))
C[:i+1] = disc * ( q * C[1:i+2] + (1-q) * C[0:i+1] )
C = C[:-1]
C[S >= H] = 0
return C[0]
barrier_binomial(K,T,S0,b,r,N,u,d,opttype='C')
I receive nothing because something is wrong and I don’t know what
But is it a simulation ?
Any help from someone ?
In your loop you are using C[S >= H] = 0, but your barrier param is defined as b. Also you are filling the array C with 0s only, so check the payoff condition. In general, I find it much easier looping through matrices when working with tree models.
I made a simple Fibonacci sequence calculator for the first 22 terms:
i=1
n=0
while i<=20000:
i = i + n
n = i - n
print(i)
Looks like the result is correct
1
2
3
5
8
13
21
34
55
89
144
233
377
610
987
1597
2584
4181
6765
10946
17711
28657
but I can't seem to find similar code anywhere online. I think that's a big red flag. Can someone tell me what is wrong here? Is this inefficient code?
No, that code is fine. The probable reason you can't find similar code online is that it's unusual to use the subtraction operator in Fibonacci, which is a purely additive function, tn = tn-2 + tn-1.
It works, of course, since addition/subtraction is both commutative and associative, meaning that order and grouping of terms is unimportant:
i = i + n # iNew = iOld + nOld
n = i - n # nNew = (iNew) - nOld
# = (iOld + nOld) - nOld
# = iOld + (nOld - nOld)
# = iOld + (0)
# = iOld
Use of subtraction allows you to bypass needing a third variable, which would be something like this in a lesser language than Python:
nextN = i + n
i = n
n = nextN
In Python, you don't actually need that since you can use tuple assignment such as:
(n, i) = (i, n + i)
With that, everything on the right of the = is evaluated before any assignments to the left.
It's an unusual way to do it, but it's correct. Your lines:
i = i + n
n = i - n
are the same as doing:
new_i = i + n
n = i
i = new_i
or,
i, n = i + n, i
which would be the usual way in Python.
trying to write a function that will calculate present value of list of cash flows. I know that numpy can do this very easily but for an assignment I have to write my own function for this :/.
Here are the three cash flows in a list as well as discount rate.
cfList = [20, 50, 90]
r = 0.05
Here's the function i've written so far. f = 0 because I want to start with the first cash flow (in this case 20). i = 1 because for the first flow its raised to the 1st power and the second flow (50) will be squared and so on.
def npv(cfList, r):
f = 0
i = 1
pv = cfList[f] / ((1 + r) ** i)
while i < len(cfList):
f += 1
i += 1
return pv
print(npv(cfList, r))
However, this output only gives me the PV of the first cashflow, and not the sum of all three from the list. If you can help i appreciate it so much thanks !
You need to sum the individual cashflows within your function and return that. At the moment you are returning the value of pv of the first cashflow as you have a return statement in your for loop.
Also, I think the way you check your while loop against i will mean that you'll miss the last payment value. Usually you don't need to instantiate counter variables yourself (see my examples below):
def npv(cfList, r):
f = 0
i = 1
pv = cfList[f] / ((1 + r) ** i) # <-- this needs to be in the loop
while i < len(cfList): # <-- i will break loop before last payment is calculated.
f += 1
i += 1
return pv # <-- this return here is the issue
print(npv(cfList, r))
NPV being the sum of PV of all future cashflows, that is what you need to calculate. E.g.:
def npv(cfList, r):
sum_pv = 0 # <-- variable used to sum result
for i, pmt in enumerate(cfList, start=1): # <-- use of enumerate allows you to do away with the counter variables.
sum_pv += pmt / ((1 + r) ** i) # <-- add pv of one of the cash flows to the sum variable
return sum_pv # <-- only return the sum after your loop has completed.
Always remember that a return statement in a for-loop will break out of the loop the first time the return is encountered.
An alternate implementation would be to yield individual PVs from a PV generator and sum the results:
def pv_gen(cfList, r):
for i, pmt in enumerate(cfList, start=1):
yield pmt / ((1 + r) ** i)
print(sum(pv_gen(cfList, r)))
Returning the NPV of a list of cash flows would look like:
def npv(cfList, r):
return sum(f / ((1 + r) ** i) for i, f in enumerate(cfList, 1))
In []:
cfList = [20, 50, 90]
r = 0.05
npv(cfList, r)
Out[]:
142.14447683835436
If you're iterating across the list using the while loop, then you should have the action taking line of code within the while loop.
It also looks like your loop will be cutting early as i = 2 = len(cflist) on the second iteration (don't forget that python uses 0 based indexing) and because the return call is within the while loop.
This should work:
def npv(cfList, r):
f = 0
i = 1
pv = 0
while f <= len(cfList):
pv += (cfList[f] / ((1 + r) ** i))
f += 1
i += 1
return pv
Need a better way to create a list of numbers, so that the run time is less. Or probably figure out a better approach to my problem.
I'm running a code to create a series of numbers based on 2 formulas. Starting from 1, the formulas create the following numbers. The idea is to return the number n from the list that is created at the end. Even tough the formulas create the same number in some cases, only unique values remain, and the list is sorted to match. I use a while loop to create the list, and I believe that reducing the number of repetitions can help with my problem, but I can't figure out a way to effectively reduce it, without ruining the purpose of my code.
def dbl_linear(n):
x = 1
y = 0
z = 0
i = 0
u = []
u.append(x)
while i <= n:
x = (u)[i]
y = 2 * x + 1
u.append(y)
z = 3 * x + 1
u.append(z)
i = i + 1
u.sort()
uFix = set(u)
uFix = list(uFix)
uFix.sort()
return uFix[n]
print(dbl_linear(50))
These are the expected results. Which I get, but it takes too long.
dbl_linear(10), 22)
dbl_linear(20), 57)
dbl_linear(30), 91)
dbl_linear(50), 175)
Your function can be considerably simplified to:
Code:
def dbl_linear(n):
u = [1]
for i in range(n):
x = u[i]
u.extend((2 * x + 1, 3 * x + 1))
return sorted(set(u))[n]
Test Code:
assert dbl_linear(10) == 22
assert dbl_linear(20) == 57
assert dbl_linear(30) == 91
assert dbl_linear(50) == 175
I am trying to use the interpolation method in python (not the built-in one) to get the root of a function given an interval.
I have done the following and don't know where I am going wrong, I have done it with bisection and I though the only difference would be the test point.
x1 and x2 are the two ends of the interval, f is the function and epsilon is the tolerance
def interpolation (x1,x2,f,epsilon):
i = 1
n = 100
while i<n:
m = (f(x2)- f(x1))/(x2-x1)
b = f(x2) - m*(x2)
p = b
print (i,p,f(p))
if f(p) == 0 or b< epsilon:
print ('The root is at ',p,'after',i,'iterations')
break
i+= 1
if f(x1)*f(p) > 0: #Equal signs
x1 = p
else:
x2 = p
Running this with f = sin(x^2) simply returns 100 iterations oscillating as follows:
code
(80, 1.3266674970489443, 0.98214554271216425)
(81, 1.4900968376899661, 0.79633049173817871)
(82, 1.3266674970489443, 0.98214554271216425)
(83, 1.4900968376899661, 0.79633049173817871)
It looks like you are trying to solve this using the secant method. The interpolation method requires three initial values.
I am not quite sure the direction you were going with your code, but I was able to adjust it a bit as following:
i = 1
n = 100
while i<n:
print x1, x2
m = (f(x2)- f(x1))/(x2-x1)
b = f(x2) - m*(x2)
p = -b/m #root for this line
# are we close enough?
if abs(f(p)) < epsilon:
print ('The root is at ',p,'after',i,'iterations')
break
i+= 1
x1 = x2
x2 = p
It solved it in 4 iterations based on my starting positions of 1,2:
1 2
2 1.52648748495
1.52648748495 1.75820676726
1.75820676726 1.7754676477
('The root is at ', 1.7724406948343991, 'after', 4, 'iterations')
In case what you actually want is to solve the problem (instead of developing a solution for exercise), I recommend you to use a ready-made module.
My first choice would be scipy.optimize.bisect() (docs)
This module has other methods, too, like Newton-Raphson, etc.