I am new to python and I am working on a finance project to solve a set of equations that enables me to go from par spread to flat spread in terms of CDS.
I have a set of data for the upfront (U) and years (i), where to set the data sample, I name upfront with x and years in y
x = [-0.007,-0.01,-0.009,-0.004,0.005,0.011,0.018,0.027,0.037,0.048]
y = [1,2,3,4,5,6,7,8,9,10]
Here are the 3 equations that I am trying to solve together:
U = A(s(i)-c)
L(i) = 1 - (1 - (s(i) / (1 - R)) ** i) / (1 - (1 / (s(i-1) - R)) ** (i - 1))
A = sum([((1 - L(i)) / (1 + r)) ** j for j in range(1, i+1)])
Detailed explanation:
The goal is to solve and list the results for all 10 values of variable s
1st equation is used to calculate the upfront amount, where s is unknown
2nd equation is used to calculate the hazard rate L, where R is recovery rate, s(i) is the current s term and s(i-1) is the previous s term.
Visual representation of equation 2:
3rd equation is used to calculate the annual risky annuity, the purpose of this equation is to calculate and sum the risk annuities. For example, if i=1, then there should be one term in the equation. If i=2, then there should be 2 terms in the equation where they are summed. This repeats until the 10th iteration where there are 10 values and they are summed.
Visual representation of equation 3:
To attempt to solve the problem, I wrote the following code (which doesn't run yet):
x = [-0.007,-0.01,-0.009,-0.004,0.005,0.011,0.018,0.027,0.037,0.048]
y = [1,2,3,4,5,6,7,8,9,10]
c = 0.01
r = 0.01
R = 0.4
def eqs(s, U, t, c=0.01, r=0.01, R=0.4):
L = 1 - (1 - (s / (1 - R)) ** t) / (1 - (1 / (1 - R)) ** (t - 1))
A = sum([((1 - L) / (1 + r)) ** j for j in range(1, i+1)])
s = (U/A) + c
return L, A, s
for U, t in zip(x, y):
s = fsolve(eq1, 0.01, (U, t,))
print(s, U, t)
Main obstacles:
I haven't found a way where I can make Equation 3 work.
I also haven't been able to pass through 2 sets of values into the for loop that then calls the function
I wasn't able to loop the previous spread value, s(i-1), back into the iteration to compute the next value
I was able to solve it manually on python by changing the third equation every iteration and inputting the previous results
I am hoping I can find some solution to my problem, thank you for your help in advance!
It took me a bit but I think I got it. Your main problem is that you can't code formulas which describe a complex problem, then call a 'magic' fsolve function and hoping that python will solve it for you, without even defining what is the unknown.
It doesn't work that way. You have to make your problem simple enough so that it can be solved with existing functions from some libraries. Python has no form of intelligence nor divination.
As I said in my comments, the fsolve() from scipy.optimise can only solve problems of the form f(x)=0.
If you want to use it, you have to transform your complex problem in a simple f(x)=0. problem.
Starting from your 3rd equation s = (U/A) + c we can deduce that s - (U/A) - c = 0
Given that A is a function of L and L is a function of s, if you define a function f(s)= s - (U/A) - c then s is the solution of f(s)=0.
It is what I did in the following code :
from scipy.optimize import fsolve
def Lambda(s,sold,R,t):
num = (1 - s / (1 - R)) ** t
den = (1 - sold / (1 - R)) ** (t - 1)
return 1-num/den
def Annuity(L,r,Aold,j):
return Aold + ((1 - L) / (1 + r)) ** j
def f(s,U, sold,R,t,r,Aold,j):
L=Lambda(s,sold,R,t)
A=Annuity(L,r,Aold,j)
return s - (U/A) - c
x = [-0.007,-0.01,-0.009,-0.004,0.005,0.011,0.018,0.027,0.037,0.048]
y = [1,2,3,4,5,6,7,8,9,10]
c = 0.01
r = 0.01
R = 0.4
sold=0.
Aold=0.
for n,(U, t) in enumerate(zip(x, y)):
j=n+1
print("j={},U={},t={}".format(j,U,t))
init = 0.01 # The starting estimate for the roots of f(s) = 0.
roots = fsolve(f,init,args=(U, sold,R,t,r,Aold,j))
s=roots[0]
L=Lambda(s,sold,R,t)
A=Annuity(L,r,Aold,j)
print("s={},L={},A={}".format(s,L,A))
print
sold=s
Aold=A
It gives following outputs :
j=1,U=-0.007,t=1
s=0.00289571337037,L=0.00482618895061,A=0.985320604999
j=2,U=-0.01,t=2
s=0.00485464221105,L=0.0113452406083,A=1.94349944361
j=3,U=-0.009,t=3
s=0.00685582655826,L=0.0180633847507,A=2.86243751076
j=4,U=-0.004,t=4
s=0.00892769166807,L=0.0251666093582,A=3.73027037175
j=5,U=0.005,t=5
s=0.0111024600844,L=0.0328696834011,A=4.53531159145
j=6,U=0.011,t=6
s=0.0120640333844,L=0.0280806661972,A=5.32937116379
j=7,U=0.018,t=7
s=0.0129604367831,L=0.0305170484121,A=6.08018387787
j=8,U=0.027,t=8
s=0.0139861021632,L=0.0351929301367,A=6.77353436882
j=9,U=0.037,t=9
s=0.0149883645118,L=0.0382416644539,A=7.41726068981
j=10,U=0.048,t=10
s=0.0159931206639,L=0.041597709395,A=8.00918297693
No idea if it's correct, but it looks likely to me. I guess you got the idea now and you will be able to make some adjustments.
The aim of the program is to:
"Write a python function J(m,x) that calculates the value of Jm(x) using the trapezium rule, with N = 10000. Use your function in a program to make a plot of the Bessel functions J0(x), J1(x) and J2(x) as a function of x from x = 0 to x = 20."
Jm(x) = (1/pi) . integrate[cos(m.theta - x.sin(theta))] from 0 --> pi
and is part of an intro to python module for a 1st year physics degree.
The line the type error originates from is from my function to integrate a function using the trapezium rule:
def integrate(f, a, b, N:int):
h = (b-a) / N
s = 0
for i in range(1,N):
c = f(a + i*h)
s = s + c
Area = h*(0.5*f(a) + 0.5*f(b) + s)
return Area
The error refers to the line " c = f(a + i*h) ": "TypeError: 'numpy.float64' object is not callable".
Given this function works in other programs I've made, I'm not sure what the origin of this error is. I am aware that scipy.integrate.quad could do the integration better, however we've been asked not to use it to demonstrate learning different techniques.
One possibility is that the problem is caused by other parts of the larger program. As someone very new to programming in general it seems likely that other problems exist which I haven't run into yet as the program doesn't reach them before turning up an error. The rest of the code is as follows:
import numpy as np
#Defining how to integrate a function using the trapezium rule
def integrate(f, a, b, N:int):
h = (b-a) / N
s = 0
for i in range(1,N):
c = f(a + i*h)
s = s + c
Area = h*(0.5*f(a) + 0.5*f(b) + s)
return Area
def func(o, m, x):
return np.cos(m*o - x*np.sin(o)) #1st attempt at defining the bessel function
def J(m,x):
return (1 / np.pi) * integrate(func(0, m, x), 0, np.pi, 10000)
#Produce range of x-values from 0 to 20.
xvals = np.linspace(0,20,200)
#Calculating the value of the bessel function for each value of x and m
for i in range(200):
for j in range(3):
bessel = J(j, xvals[i])
print("x: {}, m: {}, Val: {}".format(xvals[i], j, bessel)) #Print statement to check the program is functioning correctly before moving on to the next stage
return (1 / np.pi) * integrate(func(0, m, x), 0, np.pi, 10000)
In your function J, you are giving a function call as a parameter, i.e. its return value. Change func(0, m, x) to func and it should work.
Edit:
The correct answer was to pass a lambda expression: lambda i: func(i, m, x). Credit goes to Barmar.
So I am coding a Kinematics problem for physics. I have a formula for the displacement. The code correctly gives me the derivative (velocity) and second derivative (acceleration). But when I try to solve for a variable out of any of the derivatives I get weird errors. It will give me the value of the displacement though!
import numpy as np
import sympy
import matplotlib.pyplot as plt
from sympy import *
x, y, z, t = symbols('x y z t')
i, j, k = symbols('i j k')
init_printing(use_unicode=True)
# **********************************************************************************
#Question 1 - The position of an electron is given by r = 3.0t(i) − 4.0t^2(j) + 2.0(k) (where t is in
#seconds and the coefficients have the proper units for r to be in meters).
#(a) What is v(t) for the electron?
#(b) In unit–vector notation, what is v at t = 2.0 s?
#(c) What are the magnitude and direction of v just then?
def r(t):
return (3*t)*i-(4*t*t)*j+2*k
def v(t):
return diff(r(t), t)
def a(t):
return diff(v(t), t)
print("Questions 1 -")
print("a)")
print("r(t) = ", r(t))
print("v(t) = ", v(t))
print("a(t) = ", a(t))
print("")
print('b)')
print("R(2) = ", r(2))
print("v(2) = ", v(2))
When I hit run, this is the output:
Questions 1 -
a)
r(t) = 3*i*t - 4*j*t**2 + 2*k
v(t) = 3*i - 8*j*t
a(t) = -8*j
b)
R(2) = 6*i - 16*j + 2*k
Traceback (most recent call last):
File "/tmp/sessions/b12e4bdebdf741f3/main.py", line 48, in <module>
print("v(2) = ", v(2))
File "/tmp/sessions/b12e4bdebdf741f3/main.py", line 35, in v
return diff(r(t), t)
File "/usr/local/lib/python3.6/dist-packages/sympy/core/function.py", line 1979, in diff
return Derivative(f, *symbols, **kwargs)
File "/usr/local/lib/python3.6/dist-packages/sympy/core/function.py", line 1156, in __new__
raise ValueError("First variable cannot be a number: %i" % v)
ValueError: First variable cannot be a number: 2
Short answer:
v(2) means differentiate r(2) with respect to 2.
2 is not a symbol so you get the error. You need an additional argument in your function v().
def v(t,at_point):
return diff(r(t), t, at_point)
v(t,2)
#-8⋅j
Long answer:
The problem is the following is that when you do:
v(2)
you are asking for:
diff(r(2), 2)
The last means to Differentiate r(2) with respect to 2. 2 is not a symbol so you get the error. You need an additional argument.
def v(t,at_point):
return diff(r(t), t, at_point)
You should define your function as follows:
def v(t,t0):
return diff(r(t), t, t0)
and then call it using v(t,2)
I'm trying to learn SymPy, and I'd like to figure out how to do a cool task, deriving the normal equations for a least-squares problem symbolically.
from sympy import *
init_session()
x, y, b = Matrix(), Matrix(), Matrix()
sqNorm = (y - x*b).dot(y- x*b)
solve(diff(sqNorm, b), b)
When I run that, I get
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "/usr/local/lib/python2.7/dist-packages/sympy/core/function.py", line 1638, in diff
return Derivative(f, *symbols, **kwargs)
File "/usr/local/lib/python2.7/dist-packages/sympy/core/function.py", line 1005, in __new__
if v._diff_wrt:
File "/usr/local/lib/python2.7/dist-packages/sympy/matrices/matrices.py", line 3084, in __getattr__
"%s has no attribute %s." % (self.__class__.__name__, attr))
AttributeError: ImmutableMatrix has no attribute _diff_wrt.
I am hoping for a result like (x'x)^{-1}x'y or something. Is that possible in SymPy?
No, SymPy doesn't come with this level of abstract matrix calculus built-in. To be able to differentiate matrices, they have to have specific size and be filled with things you can differentiate in: I give an example below. That said, you may be interested in this project, which implements elements of abstract matrix calculus in SymPy by axiomatizing certain rules.
Here is a sample of you can actually do in terms of symbolic least squares with SymPy. Filling matrices with symbolic variables can be done with symarray (which uses a_0_0 notation). Then compute the residuals, differentiate, and solve.
from sympy import *
m = 3
n = 2
x = Matrix(symarray('x', (m, n)))
y = Matrix(symarray('y', (m, 1)))
b = Matrix(symarray('b', (n, 1)))
z = (y-x*b).dot(y-x*b)
vars = [b[i,0] for i in range(n)]
eqs = [z.diff(b) for b in vars]
print solve(eqs, vars)
The output, though correct, is not enlightening:
{b_0_0: ((x_0_1**2 + x_1_1**2 + x_2_1**2)*(x_0_0*y_0_0 + x_1_0*y_1_0 + x_2_0*y_2_0) - (x_0_0*x_0_1 + x_1_0*x_1_1 + x_2_0*x_2_1)*(x_0_1*y_0_0 + x_1_1*y_1_0 + x_2_1*y_2_0))/((x_0_0**2 + x_1_0**2 + x_2_0**2)*(x_0_1**2 + x_1_1**2 + x_2_1**2) - (x_0_0*x_0_1 + x_1_0*x_1_1 + x_2_0*x_2_1)**2), b_1_0: ((x_0_0**2 + x_1_0**2 + x_2_0**2)*(x_0_1*y_0_0 + x_1_1*y_1_0 + x_2_1*y_2_0) - (x_0_0*x_0_1 + x_1_0*x_1_1 + x_2_0*x_2_1)*(x_0_0*y_0_0 + x_1_0*y_1_0 + x_2_0*y_2_0))/((x_0_0**2 + x_1_0**2 + x_2_0**2)*(x_0_1**2 + x_1_1**2 + x_2_1**2) - (x_0_0*x_0_1 + x_1_0*x_1_1 + x_2_0*x_2_1)**2)}
I'm trying to obtain one of the angles of Freudenstein equation (psi):
k1 * cos(psi) - k2 * cos(fi) + k3 - cos(psi - fi) = 0
I have k1, k2, k3 and fi values. I tried the following:
from sympy import Symbol, solve, cos
x = Symbol('x')
realPsi = solve(k1 * cos(x) - k2 * cos(fi) + k3 - cos(x - fi), x)
I receive this error:
File "/usr/lib/python2.7/dist-packages/sympy/solvers/solvers.py", line 484, in solve solution = _solve(f, *symbols, **flags)
File "/usr/lib/python2.7/dist-packages/sympy/solvers/solvers.py", line 700, in _solve soln = tsolve(f_num, symbol)
File "/usr/lib/python2.7/dist-packages/sympy/solvers/solvers.py", line 1143, in tsolve "(tsolve: at least one Function expected at this point")
NotImplementedError: Unable to solve the equation(tsolve: at least one Function expected at this point
I don't use this kind of tools before, maybe I'm doing something really wrong...
Any idea?
Thanks,
Héctor.
EDIT:
Thanks for the fast response.
I tried the following (simple equation with cos):
eq = 3.2 * cos(x + 0.2).rewrite(exp) + 1.7
eq
Out[1]: 1.6*exp(I*(-x - 0.2)) + 1.6*exp(I*(x + 0.2)) + 1.7
solve(1.6*exp(I*(-x - 0.2)) + 1.6*exp(I*(x + 0.2)) + 1.7, x)
NotImplementedError: Unable to solve the equation(tsolve: at least one Function expected at this point
Am I using correctly .rewrite??
Of course it should "just work" but here is a case where, with a little help for the "simpler equation with cos" given above you can get an answer:
>>> eq=3.2*cos(x+.2)+1.7
>>> [w.n(3,chop=True) for w in solve(expand(eq.rewrite(exp)))]
[-2.33, 1.93]
NotImplementedError means what it says, namely that a solver for this type of equations is "not implemented".
You can help SymPy a bit to find the solution:
>>> k * cos(x) - m * cos(y) + n - cos(x - y)
k*cos(x) - m*cos(y) + n - cos(x - y)
>>> _.rewrite(exp)
k*(exp(I*x)/2 + exp(-I*x)/2) - .....
>>> solve(_, x)
..... long solution
You can use rewrite to transform expressions written with trigonometric functions into expressions containing complex exponentials.