How to use scipy.optimize with pymc3 random variables? - python

For my pymc3 model, I need to calculate the value E which is given as M = E - e*sinE
Here M and e are pymc3 random variables. I want to use scipy.optimize to find E from the given expression but I get the error that "Should be real value, not TensorVariable". How can use TensorVariables to calculate another random variable?
#np.vectorize
def compute_E(M, e):
"""Solve Kepler's eqns for eccentric anomaly given mean anomaly"""
f = lambda E, M=M, e=e: E - e * np.sin(E) - M
return optimize.brentq(f, 0, 2 * np.pi)
with one_planet_model:
V = pm.Uniform('V',lower=-2000,upper=2000)
e = pm.Uniform('e',lower=0,upper=1)
pomega = pm.Uniform('pomega',lower=0,upper=2*np.pi)
chi = pm.Uniform('chi',lower=0,upper=1)
T = pm.DensityDist('T',lambda value: - np.log(value) - np.log(np.log(15000 * 5)))
K = pm.DensityDist('K',lambda value: -np.log(value+1)-np.log(2001))
s = pm.DensityDist('s',lambda value: -np.log(value+1)-np.log(2001))
sd = np.sqrt(err1**2 + s**2)
M = 2 * np.pi * ((jd / T + chi) % 1)
E = compute_E(M,e)
f = 2 * np.arctan2(np.sqrt(1 + e) * np.sin(E / 2),
np.sqrt(1 - e) * np.cos(E / 2))
mu = V - K * (np.sin(f + pomega) + e * np.sin(pomega))
rv_obs = pm.Normal('rv_obs',mu=mu,sd=sd,observed=rv1)

Related

RuntimeWarning: invalid value encountered in double_scalars in python . How to resolve this error

I am trying to calculate implied volatility -
import pandas as pd
from scipy.stats import norm
from math import sqrt, exp, log, pi
import numpy as np
import scipy.stats as si
def d(sigma, S, K, r, t):
d1 = 1 / (sigma * sqrt(t)) * (log(S/K) + (r + sigma**2/2) * t)
d2 = d1 - sigma * sqrt(t)
return d1, d2
def call_price(sigma, S, K, r, t, d1, d2):
C = norm.cdf(d1) * S - norm.cdf(d2) * K * exp(-r * t)
return C
# S = spot
# K = strike
# C = price of call as predicted by Black-Scholes model
# r = risk-free interest rate
# t = time to expiration expressed in years
# C0 = price of call option from option chain
def impl_volit(S, K, r, t, C0):
# S = 35450
# K = 35500
# r = 0.01
# t = 6.0/365
# C0 = 599.2
# We need a starting guess for the implied volatility. We chose 0.5
# arbitrarily.
vol = 0.5
epsilon = 1.0 # Define variable to check stopping conditions
abstol = 1e-4 # Stop calculation when abs(epsilon) < this number
i = 0 # Variable to count number of iterations
max_iter = 1e3 # Max number of iterations before aborting
while epsilon > abstol:
# if-statement to avoid getting stuck in an infinite loop.
if i > max_iter:
break
i = i + 1
orig = vol
d1, d2 = d(vol, S, K, r, t)
function_value = call_price(vol, S, K, r, t, d1, d2) - C0
vega = S * norm.pdf(d1) * sqrt(t)
vol = -function_value/vega + vol
epsilon = abs(function_value)
return vol*100
print(impl_volit(36596.05, 30400, 3.81, 6, 6121.40))
I am getting below error:
c:\Users\Desktop\IV_Delta_calculator_cheke\conversion\impliedmoony.py:54: RuntimeWarning: divide by zero encountered in double_scalars
vol = np.double(-function_value/vega + vol)
c:\Users\Desktop\IV_Delta_calculator_cheke\conversion\impliedmoony.py:8: RuntimeWarning: invalid value encountered in double_scalars
d1 = np.double(1 / (sigma * sqrt(t)) * (log(S/K) + (r + sigma**2/2) * t))
nan
Please anyone help me to resolve this..Thanks in advance

Plot the multiple values returned by a function

My function returns 2 different values which I want to utilise in 2 different graphs using Matplotlib. How can I achieve it?
def option_value_european_put(T, m, r, sigma, mu, E):
cost_value_at_initial_t_put = []
portfolio_payoff_put = []
for e in E:
delta_t = T / m
u = (1 + (sigma * math.sqrt(delta_t)) * (math.sqrt(1 + ((mu ** 2) * delta_t) / math.pow(sigma, 2))))
v = 2 - u
option_stock_price_matrix_put = np.zeros((m + 1, m + 1))
sum = 0
k = m
start = m
for i in range(m + 1):
option_stock_price_matrix_put[i][start] = max(
(e - stock_price_binomial_model(
mu, sigma, T, m,
S
)[i][start], 0)
)
for j in range(m - 1, -1, -1):
for i in range(0, j + 1):
v_plus = option_stock_price_matrix_put[i][j + 1]
v_minus = option_stock_price_matrix_put[i + 1][j + 1]
v_t = ((((v_plus - v_minus) / (u - v)) * (1 + r * delta_t)) + (u * v_minus - v * v_plus) / (u - v)) / (
1 + r * delta_t)
option_stock_price_matrix_put[i][j] = v_t
cost_value_at_initial_t_put.append(option_stock_price_matrix_put[0][0])
for i in range(0, m+1):
sum = sum + option_stock_price_matrix_put[k][i]
portfolio_return_average = math.average(sum)
portfolio_payoff_put.append(portfolio_return_average-option_stock_price_matrix_put[0][0] )
return cost_value_at_initial_t_put, portfolio_payoff_put
I want to use cost_value_at_initial_t_put in 1 Matplotlib plot and the other value in another plot. How can I use it?
Supposing that cost_value_at_initial_t_put and portfolio_payoff_cut are both lists you can create subplots:
import matplotlib.pyplot as plt
fig, (ax_cost, ax_payoff) = plt.subplots(nrows=2)
ax_cost.plot(cost_value_at_initial_t_put)
ax_payoff.plot(portfolio_payoff_cut)

Not geting right solution with solve_ivp

I am trying to solve the differential equation using solve_ivp, but I am not getting the right solution. However, I obtained the right solution using ideint. Do I have some problems with the solve_ipv program?
ODEINT program :
# Arhenius Function
def Arhenius(a, T):
dadT = np.exp(lnA)/v * np.exp(- E / (8.3144 * T)) * c * np.abs(a) ** m * np.abs((1 - np.abs(a))) ** n
return dadT
# Initial data
pt = 100000
T0 = 273
Tf = 1500
a0 = 0.0000000001
T = np.linspace(T0, Tf, pt)
a_sol = np.zeros(pt)
dadt = np.zeros(pt)
# ODE solve
a_t = odeint(Arhenius, a0, T)
# For removing errored values and have maximum at 1
search1 = np.where(np.isclose(a_t, 1))
try:
ia_1 = search1[0][0]
a_sol[0,:] = a_t[:,0]
a_sol[0,ia_1+1:pt] = 1
except:
a_sol = a_t[:,0]
# Calculate the new derivative
dadt = np.exp(lnA) * np.exp(- E / (8.3144 * T)) * c * np.abs(a_sol) ** m * np.abs((1 - a_sol)) ** n
PROGRAM with solve_ivp :
# Arhenius Function
def Arhenius(a, T):
dadT = np.exp(lnA) * np.exp(- E / (8.3144 * T)) * c * np.abs(a) ** m * np.abs((1 - np.abs(a))) ** n
return dadT
# Initial data
pt = 100000
T0 = 273
Tf = 1500
a0 = 0.0000000001
T = np.linspace(T0, Tf, pt)
a_sol = np.zeros(pt)
dadt = np.zeros(pt)
# ODE solve
a_t = solve_ivp(Arhenius, t_span = (T0, Tf), y0 = (a0,), t_eval = T, method = 'RK45')
a_sol= a_t.y
# Calculate the new derivative
dadt = np.exp(lnA) * np.exp(- E / (8.3144 * T)) * c * np.abs(a_sol) ** m * np.abs((1 - a_sol)) ** n

Fitting a line with gradient descent

I am trying to fit a line to a couple of points using gradient descent. I am no expert on this and tried to write down the mathematical algorithm for it in python. It runs for a couple of iterations, but my predictions seem to explode at some point. Here is the code:
import numpy as np
import matplotlib.pyplot as plt
def mean_squared_error(n, A, b, m, c):
e = 0
for i in range(n):
e += (b[i] - (m*A[i] + c)) ** 2
return e/n
def der_wrt_m(n,A,b,m,c):
d = 0
for i in range(n):
d += (2 * (b[i] - (m*A[i] + c)) * (-A[i]))
return d/n
def der_wrt_c(n,A,b,m,c):
d = 0
for i in range(n):
d += (2 * (b[i] - (m*A[i] + c)))
return d/n
def update(n,A,b,m,c,descent_rate):
return descent_rate * der_wrt_m(n,A,b,m,c)), descent_rate * der_wrt_c(n,A,b,m,c))
A = np.array(((0,1),
(1,1),
(2,1),
(3,1)))
x = A.T[0]
b = np.array((1,2,0,3), ndmin=2 ).T
y = b.reshape(4)
def descent(x,y):
m = 0
c = 0
descent_rate = 0.00001
iterations = 100
n = len(x)
plt.scatter(x, y)
u = np.linspace(0,3,100)
prediction = 0
for itr in range(iterations):
print(m,c)
prediction = prediction + m * x + c
m,c = update(n,x,y,m,c,descent_rate)
plt.plot(u, u * m + c, '-')
descent(x,y)
And that's my output:
0 0
19.25 -10.5
-71335.1953125 24625.9453125
5593771382944640.0 -2166081169939480.2
-2.542705027685638e+48 9.692684648057364e+47
2.40856742196228e+146 -9.202614421953049e+145
-inf inf
nan nan
nan nan
nan nan
nan nan
nan nan
nan nan
etc...
Update: The values aren't exploding anymore, but it's still not converging in a nice manner:
# We could also solve it using gradient descent
import numpy as np
import matplotlib.pyplot as plt
def mean_squared_error(n, A, b, m, c):
e = 0
for i in range(n):
e += ((b[i] - (m * A[i] + c)) ** 2)
#print("mse:",e/n)
return e/n
def der_wrt_m(n,A,b,m,c):
d = 0
for i in range(n):
# d += (2 * (b[i] - (m*A[i] + c)) * (-A[i]))
d += (A[i] * (b[i] - (m*A[i] + c)))
#print("Dm",-2 * d/n)
return (-2 * d/n)
def der_wrt_c(n,A,b,m,c):
d = 0
for i in range(n):
d += (2 * (b[i] - (m*A[i] + c)))
#print("Dc",d/n)
return d/n
def update(n,A,b,m,c, descent_rate):
return (m - descent_rate * der_wrt_m(n,A,b,m,c)),(c - descent_rate * der_wrt_c(n,A,b,m,c))
A = np.array(((0,1),
(1,1),
(2,1),
(3,1)))
x = A.T[0]
b = np.array((1,2,0,3), ndmin=2 ).T
y = b.reshape(4)
def descent(x,y):
m = 0
c = 0
descent_rate = 0.0001
iterations = 10000
n = len(x)
plt.scatter(x, y)
u = np.linspace(0,3,100)
prediction = 0
for itr in range(iterations):
prediction = prediction + m * x + c
m,c = update(n,x,y,m,c,descent_rate)
loss = mean_squared_error(n, A, b, m, c)
print(loss)
print(m,c)
plt.plot(u, u * m + c, '-')
descent(x,y)
And now the graph looks like this after about 10000 iterations with a learning rate of 0.0001:
[4.10833186 5.21468937]
1.503547594304175 -1.9947003678083184
Whereas the least square fit shows something like this:
In your update function, you should subtract calculated gradients from current m and c
def update(n,A,b,m,c,descent_rate):
return m - (descent_rate * der_wrt_m(n,A,b,m,c)), c - (descent_rate * der_wrt_c(n,A,b,m,c))
Update: Here is the working version. I got rid of A matrix after obtaining x,y since it confuses me =). For example in your gradient calculations you have an expression d += (A[i] * (b[i] - (m*A[i] + c))) but it should be d += (x[i] * (b[i] - (m*x[i] + c))) since x[i] gives you a single element whereas A[i] gives you a list.
Also you forgot a minus sign while calculating derivative with respect to c. If your expression is (y - (m*x + c))^2) than derivative with respect to c should be 2 * (-1) * (y - (m*x + c)) since there is a minus in front of c.
# We could also solve it using gradient descent
import numpy as np
import matplotlib.pyplot as plt
def mean_squared_error(n, x, y, m, c):
e = 0
for i in range(n):
e += (m*x[i]+c - y[i])**2
e = e/n
return e/n
def der_wrt_m(n, x, y, m, c):
d = 0
for i in range(n):
d += x[i] * (y[i] - (m*x[i] + c))
d = -2 * d/n
return d
def der_wrt_c(n, x, y, m, c):
d = 0
for i in range(n):
d += (y[i] - (m*x[i] + c))
d = -2 * d/n
return d
def update(n,x,y,m,c, descent_rate):
return (m - descent_rate * der_wrt_m(n,x,y,m,c)),(c - descent_rate * der_wrt_c(n,x,y,m,c))
A = np.array(((0,1),
(1,1),
(2,1),
(3,1)))
x = A.T[0]
b = np.array((1,2,0,3), ndmin=2 ).T
y = b.reshape(4)
print(x)
print(y)
def descent(x,y):
m = 0.0
c = 0.0
descent_rate = 0.01
iterations = 10000
n = len(x)
plt.scatter(x, y)
u = np.linspace(0,3,100)
prediction = 0
for itr in range(iterations):
prediction = prediction + m * x + c
m,c = update(n,x,y,m,c,descent_rate)
loss = mean_squared_error(n, x, y, m, c)
print(loss)
print(loss)
print(m,c)
plt.plot(u, u * m + c, '-')
plt.show()
descent(x,y)

Intersections between Geodesics (shortest distance paths) on the surface of a sphere

I've searched far and wide but have yet to find a suitable answer to this problem. Given two lines on a sphere, each defined by their start and end points, determine whether or not and where they intersect. I've found this site (http://mathforum.org/library/drmath/view/62205.html) which runs through a good algorithm for the intersections of two great circles, although I'm stuck on determining whether the given point lies along the finite section of the great circles.
I've found several sites which claim they've implemented this, Including some questions here and on stackexchange, but they always seem to reduce back to the intersections of two great circles.
The python class I'm writing is as follows and seems to almost work:
class Geodesic(Boundary):
def _SecondaryInitialization(self):
self.theta_1 = self.point1.theta
self.theta_2 = self.point2.theta
self.phi_1 = self.point1.phi
self.phi_2 = self.point2.phi
sines = math.sin(self.phi_1) * math.sin(self.phi_2)
cosines = math.cos(self.phi_1) * math.cos(self.phi_2)
self.d = math.acos(sines - cosines * math.cos(self.theta_2 - self.theta_1))
self.x_1 = math.cos(self.theta_1) * math.cos(self.phi_1)
self.x_2 = math.cos(self.theta_2) * math.cos(self.phi_2)
self.y_1 = math.sin(self.theta_1) * math.cos(self.phi_1)
self.y_2 = math.sin(self.theta_2) * math.cos(self.phi_2)
self.z_1 = math.sin(self.phi_1)
self.z_2 = math.sin(self.phi_2)
self.theta_wraps = (self.theta_2 - self.theta_1 > PI)
self.phi_wraps = ((self.phi_1 < self.GetParametrizedCoords(0.01).phi and
self.phi_2 < self.GetParametrizedCoords(0.99).phi) or (
self.phi_1 > self.GetParametrizedCoords(0.01).phi) and
self.phi_2 > self.GetParametrizedCoords(0.99))
def Intersects(self, boundary):
A = self.y_1 * self.z_2 - self.z_1 * self.y_2
B = self.z_1 * self.x_2 - self.x_1 * self.z_2
C = self.x_1 * self.y_2 - self.y_1 * self.x_2
D = boundary.y_1 * boundary.z_2 - boundary.z_1 * boundary.y_2
E = boundary.z_1 * boundary.x_2 - boundary.x_1 * boundary.z_2
F = boundary.x_1 * boundary.y_2 - boundary.y_1 * boundary.x_2
try:
z = 1 / math.sqrt(((B * F - C * E) ** 2 / (A * E - B * D) ** 2)
+ ((A * F - C * D) ** 2 / (B * D - A * E) ** 2) + 1)
except ZeroDivisionError:
return self._DealWithZeroZ(A, B, C, D, E, F, boundary)
x = ((B * F - C * E) / (A * E - B * D)) * z
y = ((A * F - C * D) / (B * D - A * E)) * z
theta = math.atan2(y, x)
phi = math.atan2(z, math.sqrt(x ** 2 + y ** 2))
if self._Contains(theta, phi):
return point.SPoint(theta, phi)
theta = (theta + 2* PI) % (2 * PI) - PI
phi = -phi
if self._Contains(theta, phi):
return spoint.SPoint(theta, phi)
return None
def _Contains(self, theta, phi):
contains_theta = False
contains_phi = False
if self.theta_wraps:
contains_theta = theta > self.theta_2 or theta < self.theta_1
else:
contains_theta = theta > self.theta_1 and theta < self.theta_2
phi_wrap_param = self._PhiWrapParam()
if phi_wrap_param <= 1.0 and phi_wrap_param >= 0.0:
extreme_phi = self.GetParametrizedCoords(phi_wrap_param).phi
if extreme_phi < self.phi_1:
contains_phi = (phi < max(self.phi_1, self.phi_2) and
phi > extreme_phi)
else:
contains_phi = (phi > min(self.phi_1, self.phi_2) and
phi < extreme_phi)
else:
contains_phi = (phi > min(self.phi_1, self.phi_2) and
phi < max(self.phi_1, self.phi_2))
return contains_phi and contains_theta
def _PhiWrapParam(self):
a = math.sin(self.d)
b = math.cos(self.d)
c = math.sin(self.phi_2) / math.sin(self.phi_1)
param = math.atan2(c - b, a) / self.d
return param
def _DealWithZeroZ(self, A, B, C, D, E, F, boundary):
if (A - D) is 0:
y = 0
x = 1
elif (E - B) is 0:
y = 1
x = 0
else:
y = 1 / math.sqrt(((E - B) / (A - D)) ** 2 + 1)
x = ((E - B) / (A - D)) * y
theta = (math.atan2(y, x) + PI) % (2 * PI) - PI
return point.SPoint(theta, 0)
def GetParametrizedCoords(self, param_value):
A = math.sin((1 - param_value) * self.d) / math.sin(self.d)
B = math.sin(param_value * self.d) / math.sin(self.d)
x = A * math.cos(self.phi_1) * math.cos(self.theta_1) + (
B * math.cos(self.phi_2) * math.cos(self.theta_2))
y = A * math.cos(self.phi_1) * math.sin(self.theta_1) + (
B * math.cos(self.phi_2) * math.sin(self.theta_2))
z = A * math.sin(self.phi_1) + B * math.sin(self.phi_2)
new_phi = math.atan2(z, math.sqrt(x**2 + y**2))
new_theta = math.atan2(y, x)
return point.SPoint(new_theta, new_phi)
EDIT: I forgot to specify that if two curves are determined to intersect, I then need to have the point of intersection.
A simpler approach is to express the problem in terms of geometric primitive operations like the dot product, the cross product, and the triple product. The sign of the determinant of u, v, and w tells you which side of the plane spanned by v and w contains u. This enables us to detect when two points are on opposite sites of a plane. That's equivalent to testing whether a great circle segment crosses another great circle. Performing this test twice tells us whether two great circle segments cross each other.
The implementation requires no trigonometric functions, no division, no comparisons with pi, and no special behavior around the poles!
class Vector:
def __init__(self, x, y, z):
self.x = x
self.y = y
self.z = z
def dot(v1, v2):
return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z
def cross(v1, v2):
return Vector(v1.y * v2.z - v1.z * v2.y,
v1.z * v2.x - v1.x * v2.z,
v1.x * v2.y - v1.y * v2.x)
def det(v1, v2, v3):
return dot(v1, cross(v2, v3))
class Pair:
def __init__(self, v1, v2):
self.v1 = v1
self.v2 = v2
# Returns True if the great circle segment determined by s
# straddles the great circle determined by l
def straddles(s, l):
return det(s.v1, l.v1, l.v2) * det(s.v2, l.v1, l.v2) < 0
# Returns True if the great circle segments determined by a and b
# cross each other
def intersects(a, b):
return straddles(a, b) and straddles(b, a)
# Test. Note that we don't need to normalize the vectors.
print(intersects(Pair(Vector(1, 0, 1), Vector(-1, 0, 1)),
Pair(Vector(0, 1, 1), Vector(0, -1, 1))))
If you want to initialize unit vectors in terms of angles theta and phi, you can do that, but I recommend immediately converting to Cartesian (x, y, z) coordinates to perform all subsequent calculations.
Intersection using plane trig can be calculated using the below code in UBasic.
5 'interx.ub adapted from code at
6 'https://rosettacode.org
7 '/wiki/Find_the_intersection_of_two_linesSinclair_ZX81_BASIC
8 'In U Basic by yuji kida https://en.wikipedia.org/wiki/UBASIC
10 XA=48.7815144526:'669595.708
20 YA=-117.2847245001:'2495736.332
30 XB=48.7815093807:'669533.412
40 YB=-117.2901673467:'2494425.458
50 XC=48.7824947147:'669595.708
60 YC=-117.28751374:'2495736.332
70 XD=48.77996737:'669331.214
80 YD=-117.2922957:'2494260.804
90 print "THE TWO LINES ARE:"
100 print "YAB=";YA-XA*((YB-YA)/(XB-XA));"+X*";((YB-YA)/(XB-XA))
110 print "YCD=";YC-XC*((YD-YC)/(XD-XC));"+X*";((YD-YC)/(XD-XC))
120 X=((YC-XC*((YD-YC)/(XD-XC)))-(YA-XA*((YB-YA)/(XB-XA))))/(((YB-YA)/(XB-XA))-((YD-YC)/(XD-XC)))
130 print "Lat = ";X
140 Y=YA-XA*((YB-YA)/(XB-XA))+X*((YB-YA)/(XB-XA))
150 print "Lon = ";Y
160 'print "YCD=";YC-XC*((YD-YC)/(XD-XC))+X*((YD-YC)/(XD-XC))

Categories

Resources