Summing results from a monte carlo - python

I am trying to sum the values in the 'Callpayoff' list however am unable to do so, print(Callpayoff) returns a vertical list:
0
4.081687878300656
1.6000410648454846
0.5024316862043037
0
so I wonder if it's a special sublist ? sum(Callpayoff) does not work unfortunately. Any help would be greatly appreciated.
def Generate_asset_price(S,v,r,dt):
return (1 + r * dt + v * sqrt(dt) * np.random.normal(0,1))
def Call_Poff(S,T):
return max(stream[-1] - S,0)
# initial values
S = 100
v = 0.2
r = 0.05
T = 1
N = 2 # number of steps
dt = 0.00396825
simulations = 5
for x in range(simulations):
stream = [100]
Callpayoffs = []
t = 0
for n in range(N):
s = stream[t] * Generate_asset_price(S,v,r,dt)
stream.append(s)
t += 1
Callpayoff = Call_Poff(S,T)
print(Callpayoff)
plt.plot(stream)

Right now you're not appending values to a list, you're just replacing the value of Callpayoff at each iteration and printing it. At each iteration, it's printed on a new line so it looks like a "vertical list".
What you need to do is use Callpayoffs.append(Call_Poff(S,T)) instead of Callpayoff = Call_Poff(S,T).
Now a new element will be added to Callpayoffs at every iteration of the for loop.
Then you can print the list with print(Callpayoffs) or the sum with print(sum(Callpayoffs))
All in all the for loop should look like this:
for x in range(simulations):
stream = [100]
Callpayoffs = []
t = 0
for n in range(N):
s = stream[t] * Generate_asset_price(S,v,r,dt)
stream.append(s)
t += 1
Callpayoffs.append(Call_Poff(S,T))
print(Callpayoffs,"sum:",sum(Callpayoffs))
Output:
[2.125034975231003, 0] sum: 2.125034975231003
[0, 0] sum: 0
[0, 0] sum: 0
[0, 0] sum: 0
[3.2142923036024342, 4.1390018820809615] sum: 7.353294185683396

Related

Python List manipulation - couting common instances

I have a ListA = [1,2,3,3,2,1,3,3,1,3]
The 3s are in a sequence of 2,2,1 (2 instances, 2 instances, and 1 instance at the end)
I want to generate a ListB = [2,2,1] from the above ListA
I have code:
ls = [1,2,3,3,2,1,3,3,2,3]
pplist = []
pp = 0
for ii in range(0,len(ls)):
if ls[ii] == 3:
pp += 1
else:
if pp > 0:
pplist.append(pp)
pp = 0
print(pplist)
This gives me [2,2] and for the last element I have to add an additional if-loop.
Is there a way to achieve this without having additional code just for the last element?
(ListA could also end with multiple 3s instead of a single 3)
Thank you
R
there's a pretty easy way to do this with groupby:
from itertools import groupby
nums = [1,2,3,3,2,1,3,3,2,3]
[sum(1 for _ in v) for k, v in groupby(nums) if k == 3]
# [2, 2, 1]
edit: adding a long form version of this to make it easier to understand:
def count_nums(nums, to_count=3):
res = []
for num, vals in groupby(nums): # num is the number, vals is an iterable of the values in the group
if num == to_count:
num_vals = sum(1 for _ in vals) # could also be `len(list(vals))`, i just don't want to create a whole list solely for its length
res.append(num_vals)
return res
ls = [1,2,3,3,2,1,3,3,2,3]
pplist = []
pp = 0
for ii in range(0,len(ls)):
if ls[ii] == 3:
pp += 1
if ii == len(ls)-1:
pplist.append(pp)
else:
if pp > 0:
pplist.append(pp)
pp = 0
print(pplist)

Average length of sequence with consecutive values >100 (Python)

I am trying to identify the length of consecutive sequences within an array that are >100. I have found the longest sequence using the following code but need to alter to also find the average length.
def getLongestSeq(a, n):
maxIdx = 0
maxLen = 0
currLen = 0
currIdx = 0
for k in range(n):
if a[k] >100:
currLen +=1
# New sequence, store
# beginning index.
if currLen == 1:
currIdx = k
else:
if currLen > maxLen:
maxLen = currLen
maxIdx = currIdx
currLen = 0
if maxLen > 0:
print('Index : ',maxIdx,',Length : ',maxLen,)
else:
print("No positive sequence detected.")
# Driver code
arrQ160=resultsQ1['60s']
n=len(arrQ160)
getLongestSeq(arrQ160, n)
arrQ260=resultsQ2['60s']
n=len(arrQ260)
getLongestSeq(arrQ260, n)
arrQ360=resultsQ3['60s']
n=len(arrQ360)
getLongestSeq(arrQ360, n)
arrQ460=resultsQ4['60s']
n=len(arrQ460)
getLongestSeq(arrQ460, n)
output
Index : 12837 ,Length : 1879
Index : 6179 ,Length : 3474
Index : 1164 ,Length : 1236
Index : 2862 ,Length : 617
This should work:
def get_100_lengths( arr ) :
s = ''.join( ['0' if i < 100 else '1' for i in arr] )
parts = s.split('0')
return [len(p) for p in parts if len(p) > 0]
After that you may calculate an average or do whatever you like.
The result:
>>> get_100_lengths( [120,120,120,90,90,120,90,120,120] )
[3, 1, 2]
that might be a little tricky. You want to use one variable to keep track of sum of length, one variable to keep track of how many times a sequence occurred.
We can determine if a sequence terminated when current number<100 and previous number is greater than 100
def getLongestSeq(array):
total_length = total_ct = 0
last_is_greater = False
for number in array:
if number > 100:
total_length += 1
last_is_greater = True
elif number<100 and last_is_greater:
total_ct += 1
last_is_greater = False
return round(total_length / total_ct)
Did not test this code, please comment if there is any issue
You want to find all the sequences, take their lengths, and get the average. Each of those steps are relatively straightforward.
items = [1, 101, 1, 101, 101, 1, 101, 101, 101, 1]
Finding sequences: use groupby.
from itertools import groupby
groups = groupby(items, lambda x: x > 100) # (False, [1]), (True, [101]), ...
Find lengths (careful, iterable of iterables not a list):
lens = [len(g) for k, g in groups if k] # [1, 2, 3]
Find average (assumes at least one):
avg = float(sum(lens)) / len(lens) # 2.0

How to slice array quickly based on conditions?

I have a giant nested for loop....10 in all, but for illustration here, i am including 6. I am doing a summation (over multiple indices; the incides are not independent!). The index in any inner for loop depends on the index of the outer loop (except for one instance). The inner-most loop contains an operation where i slice an array (named 'w') based on 8 different conditions all combined using '&' and '|'. There is also this 'HB' function that takes as an argument this sliced array (named 'wrange'), performs some operations on it and returns an array of the same size.
The timescale for this slicing and the 'HB' function to execute is 300-400 microseconds and 100 microseconds respectively. I need to bring it down drastically. To nanoseconds.!!
Tried using dictionary instead of array (where i am slicing). It is much slower. Tried storing the sliced array for all possible values. That is a very huge computation in its own right since there are many many possible combinations of the conditions (these conditions depend indirectly on the indices of the for loop)
s goes from 1 to 49
t goes from -s to s
and there are 641 combinations of l,n
Here, i have posted one value of s,t and an l,n combination for illustration.
s = 7
t = -7
l = 72
n = 12
Nl = Dictnorm[n,l]
Gamma_l = Dictfwhm[n,l]
Dictc1 = {}
Dictc2 = {}
Dictwrange = {}
DictH = {}
DictG = {}
product = []
startm = max(-l-t,-l)
endm = min(l-t,l)+1
sum5 = 0
for sp in range(s-2,s+3): #s'
sum4 = 0
for tp in range(-sp,-sp+1): #t'
#print(tp)
sum3 = 0
integral = 1
for lp in range(l-2,l+3): #l'
sum2 = 0
if (n,lp) in Dictknl2.keys():
N1 = Dictnorm[n,lp]
Gamma_1 = Dictfwhm[n,lp]
for lpp in range(l-2,l+3): #l"
sum1 = 0
if ((sp+lpp-lp)%2 == 1 and sp>=abs(lpp-lp) and
lp>=abs(sp-lpp) and lpp>=abs(sp-lp) and
(n,lpp) in Dictknl2.keys()):
F = f(lpp,lp,sp)
N2 = Dictnorm[n,lpp]
Gamma_2 = Dictfwhm[n,lpp]
for m in range(startm, endm): #m
sum0 = 0
L1 = LKD(n,l,m,l,m)
L2 = LKD(n,l,m+t,l,m+t)
for mp in range(max(m+t-tp-5,m-5),
min(m+5,m+t-tp+5)+1): #m'
if (abs(mp)<=lp and abs(mp)<=lpp and
abs(mp+tp)<=lp and abs(mp+tp)<=lpp
and LKD(n,l,m,lp,mp)!=0
and LKD(n,l,m+t,lpp,mp+tp)!=0):
c3 = Dictomega[n,lp,mp+tp]
c4 = Dictomega[n,lpp,mp]
wrange = np.unique(np.concatenate
((Dictwrange[m],
w[((w>=(c3-Gamma_1))&
((c3+Gamma_1)>=w))|
((w>=(c4-Gamma_2))&
((c4+Gamma_2)>=w))])))
factor = (sum(
HB(Dictc1[n,l,m+t],
Dictc2[n,l,m],Nl,
Nl,Gamma_l,
Gamma_l,wrange,
Sigma).conjugate()
*HB(c3,c4,N1,N2,Gamma_1,
Gamma_2,wrange,0)*L1*L2)
*LKD(n,l,m,lp,mp)
*LKD(n,l,m+t,lpp,mp+tp) *DictG[m]
*gamma(lpp,sp,lp,tp,mp)
*F)
sum0 = sum0 + factor #sum over m'
sum1 = sum1 + sum0 #sum over m
sum2 = sum2 + sum1 #sum over l"
sum3 = sum3 + sum2 #sum over l'
sum4 = sum4 + sum3*integral #sum over t'
sum5 = sum5 + sum4 #sum over s'
z = (1/(sum(product)))*sum5
print(z.real,z.imag,l,n)
TL;DR
def HB(a,...f,array1): #########timesucker
perform_some_operations_on_array1_using_a_b_c_d
return operated_on_array1
for i in ():
for j in ():
...
...
for o in ():
array1 = w[w>some_function1(i,j,..k) &
w<some_function2(i,j,..k) |.....] #########timesucker
factor = HB(a,....f,array1) * HB(g,...k,array1) *
alpha*beta*gamma....
It takes about 30 seconds to run this whole section once. I need to bring it down to as low as possible. 1 second is the minimum target

Summation from sub list

If n = 4, m = 3, I have to select 4 elements (basically n elements) from a list from start and end. From below example lists are [17,12,10,2] and [2,11,20,8].
Then between these two lists I have to select the highest value element and after this the element has to be deleted from the original list.
The above step has to be performed m times and take the summation of the highest value elements.
A = [17,12,10,2,7,2,11,20,8], n = 4, m = 3
O/P: 20+17+12=49
I have written the following code. However, the code performance is not good and giving time out for larger list. Could you please help?
A = [17,12,10,2,7,2,11,20,8]
m = 3
n = 4
scoreSum = 0
count = 0
firstGrp = []
lastGrp = []
while(count<m):
firstGrp = A[:n]
lastGrp = A[-n:]
maxScore = max(max(firstGrp), max(lastGrp))
scoreSum = scoreSum + maxScore
if(maxScore in firstGrp):
A.remove(maxScore)
else:
ai = len(score) - 1 - score[::-1].index(maxScore)
A.pop(ai)
count = count + 1
firstGrp.clear()
lastGrp.clear()
print(scoreSum )
I would like to do that this way, you can generalize it later:
a = [17,12,10,2,7,2,11,20,8]
a.sort(reverse=True)
sums=0
for i in range(3):
sums +=a[i]
print(sums)
If you are concerned about performance, you should use specific libraries like numpy. This will be much faster !
A = [17,12,10,2,7,11,20,8]
n = 4
m = 3
score = 0
for _ in range(m):
sublist = A[:n] + A[-n:]
subidx = [x for x in range(n)] + [x for x in range(len(A) - n, len(A))]
sub = zip(sublist, subidx)
maxval = max(sub, key=lambda x: x[0])
score += maxval[0]
del A[maxval[1]]
print(score)
Your method uses a lot of max() calls. Combining the slices of the front and back lists allows you to reduce the amounts of those max() searches to one pass and then a second pass to find the index at which it occurs for removal from the list.

"for" loop x value?

I'm trying to get my second array to print x in increments but reset to zero once the case value changes.
Code:
array = ['2017001677', '2017001677', '2017001621', '2017001621']
array2 = ['2017001677', '2017001621']
x = 0
for case in array:
for case2 in array2:
if(case == case2):
print(case2)
print(x)
x = x + 1
Current Output:
2017001677
0
2017001677
1
2017001621
2
2017001621
3
Desired Output:
2017001677
0
2017001677
1
2017001621
0
2017001621
1
How do I accomplish this?
You can reset the counter for unique values in array by tracking the last-seen value, starting with None
array = ['2017001677', '2017001677', '2017001621', '2017001621']
array2 = ['2017001677', '2017001621']
last_case = None
for case in array:
if case != last_case:
x = 0
last_case = case
for case2 in array2:
if(case == case2):
print(case2)
print(x)
x = x + 1

Categories

Resources