Calibration of Black Karasinski model - python

I'm very new to QuantLib python package and I've been trying to run and understand this python written code for the Calibration of Black Karasinski model but I have problem on the line ql.CalibrationHelper.RelativePriceError. I'm always getting the error message: AttributeError: 'function' object has no attribute 'RelativePriceError'.
Please anyone with idea on what is wrong?
import QuantLib as ql
from collections import namedtuple
import math
displacement = 0.
voltype = ql.Normal
def create_swaption_helpers(data, index, term_structure, engine):
nominal = 1.0
swaptions = [ql.SwaptionHelper(ql.Period(swap.start, ql.Years),
ql.Period(swap.length, ql.Years),
ql.QuoteHandle(ql.SimpleQuote(swap.volatility)),
index, index.tenor(),
index.dayCounter(), index.dayCounter(),
term_structure,
ql.CalibrationHelper.RelativePriceError,
ql.nullDouble(),
nominal,
ql.ShiftedLognormal,
displacement) for swap in data]
for swap in swaptions:
swap.setPricingEngine(engine)
return swaptions
def calibration_report(swaptions, data):
print ("-"*82)
print ("%15s %15s %15s %15s %15s" %
"Model Price", "Market Price", "Implied Vol", "Market Vol", "RelError")
print ("-"*82)
cum_err = 0.0
for i, s in enumerate(swaptions):
model_price = s.modelValue()
market_vol = data[i].volatility
black_price = s.blackPrice(market_vol)
rel_error = model_price/black_price - 1.0
implied_vol = s.impliedVolatility(model_price,
1e-5, 50, 0.0, 0.50)
rel_error2 = implied_vol/market_vol-1.0
cum_err += rel_error2*rel_error2
print ("%15.5f %15.5f %15.5f %15.5f %15.5f" %
model_price, black_price, implied_vol, market_vol, rel_error)
print ("-"*82)
print ("Cumulative Error : %15.5f" % math.sqrt(cum_err))
today = ql.Date(15, ql.February, 2002);
settlement= ql.Date(19, ql.February, 2002);
term_structure = ql.YieldTermStructureHandle(
ql.FlatForward(settlement,0.04875825,ql.Actual365Fixed())
)
index = ql.Euribor1Y(term_structure)
CalibrationData = namedtuple("CalibrationData",
"start, length, volatility")
data = [CalibrationData(1, 5, 0.1148),
CalibrationData(2, 4, 0.1108),
CalibrationData(3, 3, 0.1070),
CalibrationData(4, 2, 0.1021),
CalibrationData(5, 1, 0.1000 )]
model = ql.BlackKarasinski(term_structure)
engine = ql.TreeSwaptionEngine(model, 100)
swaptions = create_swaption_helpers(data, index, term_structure, engine)
optimization_method = ql.LevenbergMarquardt(1.0e-8,1.0e-8,1.0e-8)
end_criteria = ql.EndCriteria(10000, 100, 1e-6, 1e-8, 1e-8)
model.calibrate(swaptions, optimization_method, end_criteria)

This is a problem in the package. It comes from a class in the underlying C++ library being renamed. The package tried to provide an alias for backwards compatibility, but it didn't work.
To work around it, use ql.BlackCalibrationHelper.RelativePriceError instead (i.e., the new name of the class).

Related

Create a pandas Data Frame containing all objects of the class in OOP

I'm trying to develop a class in python (Object Oriented). I want to keep the information of each defined object from that class into a pandas data frame, so at the end, I get a data frame that contains all of my object's info in it. How's that possible?
What I've done until now is:
class SupplyChain:
def __init__(self, projectName, frame_type, NBeams, NColumns, TotalFrameWeight, Dist,
RegisterationDate, EarliestPossibleSendTime, LatestSendTime, CurrentDay = 0):
self.Name = projectName
self.FrameType = frame_type
self.TotalBeams = NBeams
self.TotalColumns = NColumns
self.TotalFrameWeight = TotalFrameWeight
self.DistanceToSite = Dist
self.DateofRegistration = RegisterationDate
self.EarliestDelivery = self.DateofRegistration + EarliestPossibleSendTime
self.LatestDelivery = self.DateofRegistration + LatestSendTime
self.CurrentDate = CurrentDay
self.FrameCost = self.TotalFrameWeight * 1000 * 31000
if self.DistanceToSite <= 1000:
self.TransportationCost = self.DistanceToSite * self.TotalFrameWeight * 20000
else :
self.TransportationCost = 1000 * TotalFrameWeight * 20000 + ( self.DistanceToSite - 1000 ) * self.TotalFrameWeight * 25000
self.IsDelivered = 0
self.DateofDelivery = 0
self.StorageCost = 0.01 * self.FrameCost * (self.DateofDelivery - self.DateofRegistration)
if self.DateofDelivery > self.LatestDelivery :
self.DelayCost = 0.05 * self.FrameCost * (self.DateofDelivery - self.LatestDelivery)
else:
self.DelayCost = 0
self.Profit = self.FrameCost + self.TransportationCost - self.StorageCost - self.DelayCost
Columns = ["Name", "Type", "Number of Beams", "Number of Columns", "Total Weight","Distance to Site Location",
"Date of Registeration", "Earliest Time to Deliver", "Latest Time to Deliver", "Current Day",
"Frame Cost", "Transportation Cost", "Is Delivered?", "Date of Delivery", "Cost of Storage",
"Cost of Delay", "Project Profit" ]
self.df = pd.DataFrame(columns=Columns)
def PandasDataFrame(self):
self.df.loc[len(self.df.index)] = [self.Name, self.FrameType, self.TotalBeams, self.TotalColumns,
self.TotalFrameWeight, self.DistanceToSite, self.DateofRegistration,
self.EarliestDelivery, self.LatestDelivery, self.CurrentDate, self.FrameCost,
self.TransportationCost, self.IsDelivered, self.DateofDelivery,
self.StorageCost, self.DelayCost, self.Profit]
return self.df
I know it's not what I want, but I couldn't think of any other way.
Create a dataframe outside the class with the desired columns which will be scoped to the module.
Reference the dataframe from step 1 using the global keyword within the init function of SupplyChain.
Here is some code to give you an idea. You'll have to add the calculated parameters you made but other than that should be good to go.
import pandas as pd
class SupplyChain:
def __init__(self, projectName, frame_type, NBeams, NColumns, TotalFrameWeight, Dist, RegisterationDate, EarliestPossibleSendTime, LatestSendTime, CurrentDay):
self.projectName = projectName
self.frame_type = frame_type
self.NBeams = NBeams
self.NColumns = NColumns
self.TotalFrameWeight = TotalFrameWeight
self.Dist = Dist
self.RegisterationDate = RegisterationDate
self.EarliestPossibleSendTime = EarliestPossibleSendTime
self.LatestSendTime = LatestSendTime
self.CurrentDay = CurrentDay
# Append the parameters to the global dataframe
global df
df = df.append({"projectName": self.projectName, "frame_type": self.frame_type, "NBeams": self.NBeams, "NColumns": self.NColumns, "TotalFrameWeight": self.TotalFrameWeight, "Dist": self.Dist, "RegisterationDate": self.RegisterationDate, "EarliestPossibleSendTime": self.EarliestPossibleSendTime, "LatestSendTime": self.LatestSendTime, "CurrentDay": self.CurrentDay}, ignore_index=True)
# Create a global dataframe
df = pd.DataFrame(columns=["projectName", "frame_type", "NBeams", "NColumns", "TotalFrameWeight", "Dist", "RegisterationDate", "EarliestPossibleSendTime", "LatestSendTime", "CurrentDay"])
# Create an instance of the class
my_instance = SupplyChain("Project1", "frame_type1", 10, 5, 1000, 100, "2022-12-13", "2022-12-15", "2022-12-20", "2022-12-21")

PCA using MDAanalysis (python3.7)

I started to work in the field of computational chemistry and I was ask to do Principal Component Analysis on some trajectory from molecular dynamics. I was told to use MDAnalysis package, thus I find one tutorial on their page a tried to follow it (but I included my own inputs of course) to see if it will be working. I have never done analysis like this ad I am also new to python coding.
I attached my code inspired by tutorial. But it doesnt work for me, it raises many errors, one of the errors is that it cant take my inputs (topology is PDB file, coordinate is XTC file), but those are formats which are listed in supported formats or other error is that "class PCA" is not defined.
I didnt find much about dealing with PCA using MDAanalysis from other people, thus I hoped that here I could find someone, who have ever done something like this and could, please, help me. I have alreadz tried related subreddits, but without result.
from __future__ import division, absolute_import
import MDAnalysis as mda
import MDAnalysis.analysis.pca as pca
from six.moves import range
import warnings
import numpy as np
import scipy.integrate
from MDAnalysis import Universe
from MDAnalysis.analysis.align import _fit_to
from MDAnalysis.lib.log import ProgressMeter
u = mda.Universe("L22trial.pdb", "L22trial.xtc")
PCA = mda.analysis.pca.PCA
class PCA():
pca = PCA(u, select='backbone').run()
pca_space = pca.transform(u.select_atoms('backbone'))
def __init__(self, universe, select='all', align=False, mean=None,
n_components=None, **kwargs):
super(PCA, self).__init__(universe.trajectory, **kwargs)
self._u = universe
self.align = align
self._calculated = False
self.n_components = n_components
self._select = select
self._mean = mean
def _prepare(self):
self._u.trajectory[self.start]
self._reference = self._u.select_atoms(self._select)
self._atoms = self._u.select_atoms(self._select)
self._n_atoms = self._atoms.n_atoms
if self._mean is None:
self.mean = np.zeros(self._n_atoms*3)
self._calc_mean = True
else:
self.mean = self._mean.positions
self._calc_mean = False
if self.n_frames == 1:
raise ValueError('No covariance information can be gathered from a single trajectory frame.\n')
n_dim = self._n_atoms * 3
self.cov = np.zeros((n_dim, n_dim))
self._ref_atom_positions = self._reference.positions
self._ref_cog = self._reference.center_of_geometry()
self._ref_atom_positions -= self._ref_cog
if self._calc_mean:
interval = int(self.n_frames // 100)
interval = interval if interval > 0 else 1
format = ("Mean Calculation Step %(step)5d/%(numsteps)d [%(percentage)5.1f%%]")
mean_pm = ProgressMeter(self.n_frames if self.n_frames else 1, interval=interval, verbose=self._verbose, format=format)
for i, ts in enumerate(self._u.trajectory[self.start:self.stop:self.step]):
if self.align:
mobile_cog = self._atoms.center_of_geometry()
mobile_atoms, old_rmsd = _fit_to(self._atoms.positions, self._ref_atom_positions, self._atoms, mobile_com=mobile_cog, ref_com=self._ref_cog)
else:
self.mean += self._atoms.positions.ravel()
mean_pm.echo(i)
self.mean /= self.n_frames
self.mean_atoms = self._atoms
self.mean_atoms.positions = self._atoms.positions
def _single_frame(self):
if self.align:
mobile_cog = self._atoms.center_of_geometry()
mobile_atoms, old_rmsd = _fit_to(self._atoms.positions, self._ref_atom_positions, self._atoms, mobile_com=mobile_cog, ref_com=self._ref_cog)
x = mobile_atoms.positions.ravel()
else:
x = self._atoms.positions.ravel()
x -= self.mean
self.cov += np.dot(x[:, np.newaxis], x[:, np.newaxis].T)
def _conclude(self):
self.cov /= self.n_frames - 1
e_vals, e_vects = np.linalg.eig(self.cov)
sort_idx = np.argsort(e_vals)[::-1]
self.variance = e_vals[sort_idx]
self.variance = self.variance[:self.n_components]
self.p_components = e_vects[:self.n_components, sort_idx]
self.cumulated_variance = (np.cumsum(self.variance) / np.sum(self.variance))
self._calculated = True
def transform(self, atomgroup, n_components=None, start=None, stop=None, step=None):
if not self._calculated:
raise ValueError('Call run() on the PCA before using transform')
if isinstance(atomgroup, Universe):
atomgroup = atomgroup.atoms
if(self._n_atoms != atomgroup.n_atoms):
raise ValueError('PCA has been fit for {} atoms. Your atomgroup has {} atoms'.format(self._n_atoms, atomgroup.n_atoms))
if not (self._atoms.types == atomgroup.types).all():
warnings.warn('Atom types do not match with types used to fit PCA')
traj = atomgroup.universe.trajectory
start, stop, step = traj.check_slice_indices(start, stop, step)
n_frames = len(range(start, stop, step))
dim = (n_components if n_components is not None else self.p_components.shape[1])
dot = np.zeros((n_frames, dim))
for i, ts in enumerate(traj[start:stop:step]):
xyz = atomgroup.positions.ravel() - self.mean
dot[i] = np.dot(xyz, self.p_components[:, :n_components])
return dot
def cosine_content(pca_space, i):
t = np.arange(len(pca_space))
T = len(pca_space)
cos = np.cos(np.pi * t * (i + 1) / T)
return ((2.0 / T) * (scipy.integrate.simps(cos*pca_space[:, i])) ** 2 /
scipy.integrate.simps(pca_space[:, i] ** 2))
it seems you copied and pasted the PCA class itsefl. My guess is that you don't need to do this (I have never used that module so it s just a guess).
The documentation ( https://www.mdanalysis.org/docs/documentation_pages/analysis/pca.html ) seems to indicate the only thing you need to do is the following
import MDAnalysis as mda
import MDAnalysis.analysis.pca as pca
u = mda.Universe("L22trial.pdb", "L22trial.xtc")
mypca = pca.PCA(u, select='backbone').run()
pca_space = mypca.transform(u.select_atoms('backbone'))
If you have an error message "No module named 'MDAnalysis.analysis.pca.PCA'; 'MDAnalysis.analysis.pca' is not a package" it means what it says :-).
That means there is no package on your computer named MDAnalysis. to fix this you need to install using pip install command or conda if you use conda package manager. See this link https://www.mdanalysis.org/pages/installation_quick_start/
Looking at the link https://www.mdanalysis.org/docs/_modules/MDAnalysis/analysis/pca.html from which you got inspired it confirmed my first guess and I think my answer should allow you using that package.

How to build a correct linking constraint in Pyomo - Mixed Integer Linear program?

Context: I am working on an assignment for which I am using Pyomo in order to learn this framework.
Here is the assignment :
From this problem, I understand that I should be introducing a binary variable in order to trigger the fixed cost constraint.
Here is my implementation :
from pyomo.environ import *
VERY_LARGE_NUMBER = 1e8
def part_4_april(data, limit_ballons, limit_labor):
model = ConcreteModel()
PACKAGES = data.keys()
model.x = Var(PACKAGES, within=NonNegativeReals)
model.y = Var(PACKAGES, within=Binary)
model.profit = Objective(
expr=sum(
(
(data[p]["price"] - data[p]["cost"]) * model.x[p]
- data[p]["fixed_cost"] * model.y[p]
)
for p in PACKAGES
),
sense=maximize,
)
model.ballon_cst = Constraint(
expr=sum(data[p]["ballons"] * model.x[p] for p in PACKAGES) <= limit_ballons
)
model.labor_cst = Constraint(
expr=sum(data[p]["labor"] * model.x[p] for p in PACKAGES) <= limit_labor
)
model.fixed_cost_cst = Constraint(
expr=sum(model.x[p] - VERY_LARGE_NUMBER * model.y[p] for p in PACKAGES) <= 0
)
opt = SolverFactory("cbc")
results = opt.solve(model, tee=True)
model.pprint()
return model
if __name__ == "__main__":
# part 4
data = {
"Standard": {"labor": 3, "ballons": 2, "cost": 2, "price": 3, "fixed_cost": 10},
"Joyful": {"labor": 5, "ballons": 5, "cost": 3, "price": 5, "fixed_cost": 5},
"Fabulous": {"labor": 8, "ballons": 8, "cost": 4, "price": 7, "fixed_cost": 1},
}
model = part_4_april(data, limit_ballons=360, limit_labor=500)
print("----- PART 4: April -----")
print("Profit:", model.profit())
for c in data.keys():
print(" ", c, ":", model.x[c]())
The code does not produce the expected output, instead, it must produce the following output :
# must produce :
# Profit: 188.0
# Standard : 140.0
# Joyful : 0.0
# Fabulous : 10.0
Is there a problem with my code or the way I use the binary variables ?
I finally found the solution with the comment from Bethany Nicholson and Erwin Kalvelangen - there were two issues with my code. First, the fixed cost must not contain sum and should be applied to all packages individually
# NOT...
# model.fixed_cost_cst = Constraint(
# expr=sum(model.x[p] - VERY_LARGE_NUMBER * model.y[p] for p in PACKAGES) <= 0
# )
# must be applied to all packages individually
def fixed_cost_rule(model, p):
return model.x[p] - VERY_LARGE_NUMBER * model.y[p] <= 0
model.fixed_cost_cst = Constraint(PACKAGES, rule=fixed_cost_rule)
Second, the result must be 159 and not 188.

No value for uninitialized NumericValue object - Pyomo

I'm working on an optimization model in python with the pyomo library (I just started using this). I can model in excel with the necessary constraints. However I'm getting an error message in python that I cannot seem to understand. The code and error message is below.
All help will be appreciated. Thanks
from scipy.stats import norm
setup_cost = 125
holding_cost = 17
annual_demand = 1200
std_annual_demand = 70
lead_time = 1/52
ltd = annual_demand*lead_time
std_ltd = 9.707
model = ConcreteModel()
model.order_quantity = Var(bounds = (0,None))
model.multiple_k = Var(bounds = (0,None))
def total_annual_cost(model):
orders_per_year = annual_demand/model.order_quantity
safety_stock = model.multiple_k * std_ltd
annual_ordering_cost = orders_per_year * setup_cost
annual_holding_cost = holding_cost*(safety_stock+model.order_quantity/2)
total_cost = annual_holding_cost + annual_ordering_cost
return total_cost
def service_level(model):
k = value(model.multiple_k)
order_quantity = value(model.order_quantity)
#expected_shortage_per_cycle = (norm.pdf(model.multiple_k)-model.multiple_k*(1-norm.cdf(model.multiple_k))) * std_ltd
expected_shortage_per_cycle = (norm.pdf(k)- k *(1-norm.cdf(k))) * std_ltd
service_level = 1-expected_shortage_per_cycle/order_quantity
return service_level
#model.service_level = Expression(initialize = ((norm.pdf(model.multiple_k)-model.multiple_k*(1-norm.cdf(model.multiple_k))) * std_ltd))
model.service_level_constraint = Constraint(rule = service_level)
model.objective = Objective(rule = total_annual_cost, sense = 1)
solver = SolverFactory('ipopt')
status = solver.solve(model)
ERROR: evaluating object as numeric value: multiple_k
(object: )
No value for uninitialized NumericValue object multiple_k
ERROR: Rule failed when generating expression for constraint
service_level_constraint: ValueError: No value for uninitialized
NumericValue object multiple_k
ERROR: Constructing component 'service_level_constraint' from data=None
failed: ValueError: No value for uninitialized NumericValue object
multiple_k
This is not a complete answer, but you are using functions (norm.pdf and norm.cdf) that can't be used with model variables in a mathematical programming model.
If you are to use such function, you have to use them on parameters only. And if you want to use them with model variables as an argument, it might be interesting to rewrite them directly in your model. While it is easy to do so for norm.pdf, it might be harder with norm.cdf as the formula to compute it is indefinite.
See the question at Probability distributions in pyomo for a discussion on how to use or adapt norm.cdf into an optimization model. I also posted a more general question on the OR StackExchange site here because this is a mathematical formulation common to all AMLs.
Thanks to the suggestion of #V. Brunelle, I rewrote the pdf and cdf functions directly into the constraint and it worked like magic.
from pyomo.environ import *
setup_cost = 125
holding_cost = 17
annual_demand = 1200
std_annual_demand = 70
lead_time = 1/52
ltd = annual_demand*lead_time
std_ltd = 9.707
model = ConcreteModel()
model.order_quantity = Var(bounds = (0,None))
model.multiple_k = Var(bounds = (0,None))
def total_annual_cost(model):
safety_stock = model.multiple_k * std_ltd
orders_per_year = annual_demand/model.order_quantity
annual_ordering_cost = orders_per_year * setup_cost
annual_holding_cost = holding_cost*(safety_stock+(model.order_quantity/2))
total_cost = annual_holding_cost + annual_ordering_cost
return total_cost
def service_level_req(model):
e = np.exp(1)
pi = np.pi
pdf = e**(-((model.multiple_k ** 2)/2))/np.sqrt(2*np.pi)
cdf = 1/(1+ (e**(-(model.multiple_k * 1.65451))))
expected_shortage_per_cycle = (pdf - ((1-cdf)*model.multiple_k))* std_ltd
service_level = 1-expected_shortage_per_cycle/model.order_quantity
return service_level >= .98
def turn_requirement(model):
rop = model.multiple_k * std_ltd + ltd
max_rop = model.order_quantity-1 + rop
turn = annual_demand/max_rop
return turn >= 6
model.sl_const = Constraint(rule = service_level_req)
model.turn_const = Constraint(rule = turn_requirement)
model.objective = Objective(rule = total_annual_cost, sense = 1)
solver = SolverFactory('ipopt')
status = solver.solve(model)

ModuleNotFoundError: No module named 'breezypythongui'

I have created GUI program in python which converts C2F and F2C when I run my program I get an error though I imported module correctly. Can anyone please help me to solve an error
Code:
from breezypythongui import EasyFrame
#from tkinter import PhotoImage
from tkinter import *
class ProgDemo(EasyFrame):
def __init__(self):
EasyFrame.__init__(self,width="600", title = "Program")
self.addLabel(text = "Temp",row = 1, column = 0)
self.getinput = self.addFloatField(value = 0.0,row = 1,column = 1)
self.addLabel(text = "Output",row = 2, column = 0)
self.op = self.addFloatField(value = 0.0,row = 2,column = 1)
self.grp1 = self.addRadiobuttonGroup(row = 3,column = 0)
C_to_F = self.grp1.addRadiobutton(text = "C to F")
F_to_C = self.grp1.addRadiobutton(text = "F to C")
self.conBtn = self.addButton(text = "convert",row = 5, column = 0,command = self.tempc)
self.resetBtn = self.addButton(text = "reset",row = 5, column = 1,command = self.reseti)
def tempc(self):
ipval = self.getinput.getNumber()
if self.grp1.getSelectedButton()["value"] == "C to F":
op = 9.0/5.0 * ipval + 32
else:
op = (ipval - 32) * 5.0/9.0
self.op.setValue(op)
def reseti(self):
self.getinput.setValue(0);
self.op.setValue(0);
def main():
ProgDemo().mainloop()
if __name__ == "__main__":
main()
Screenshot:
It seems like, the module is missing and you need it.
So download and install it: http://home.wlu.edu/~lambertk/breezypythongui/
You need to have the module breezepythongui.py and your python code in the same folder. Not only having the folder but both modules must be in the same folder.
For example; My python code "myfirstguiproject.py" and "breezypythongui.py" are in the same folder.
I know when you extract the downloaded zip file named breezypythongui.zip, it will create a folder and in that folder there is the "breezypythongui.py" module. You need to get rid of the folder and only keep the module (breezypythongui.py).

Categories