<jupyter_start><jupyter_text>Calling QuantSA from pythonThe following is an example of calling the QuantSA dlls from Python. The paths below are absolute and based on the the location of my compiled dlls but it should be easy for you to work out how to change that for your own locations. Examples of using the Library TechnicalitiesThe main QuantSA library is written in C.  There are many reasons why this makes sense: * It is a type-safe, object-oriented language - good for building and maintaining large code bases. * It is easier to learn and write than C++ * It is faster than Python or Matlab * It is even becoming portable * It plays nicely with the typical bank employee's Microsoft Windows and Office environment Nevertheless Python (or Matlab) remain much more convenient for scientific computing where you are experimenting with different models and methods and so it could be useful to be able to mix command line style exploration and a more complete library.  Letting Python see the C Library:<jupyter_code>import clr # to be able to use the C# library

clr.AddReference("System.Collections")
clr.AddReference(r'C:\Dev\QuantSAFolder\QuantSA\QuantSA\QuantSA.Excel.AddIn\bin\Debug\QuantSA.Shared.dll')
clr.AddReference(r'C:\Dev\QuantSAFolder\QuantSA\QuantSA\QuantSA.Excel.AddIn\bin\Debug\QuantSA.Core.dll')
clr.AddReference(r'C:\Dev\QuantSAFolder\QuantSA\QuantSA\QuantSA.Excel.AddIn\bin\Debug\QuantSA.CoreExtensions.dll')
clr.AddReference(r'C:\Dev\QuantSAFolder\QuantSA\QuantSA\QuantSA.Excel.AddIn\bin\Debug\QuantSA.Valuation.dll')

from System.Collections.Generic import List

from QuantSA.Shared.Dates import *
print("The library is ready to use!")<jupyter_output><empty_output><jupyter_text>Load Static Data<jupyter_code>from QuantSA.CoreExtensions.Data import *
from QuantSA.Shared.State import *

SharedDataLoader.LoadFromFolder(r"C:\Dev\QuantSAFolder\QuantSA\QuantSA\QuantSA.Excel.AddIn\bin\Debug")
zar = QuantSAState.GetCurrency("ZAR")
jibar = QuantSAState.GetFloatRateIndex("ZAR.JIBAR.3M")

print(zar)
print(jibar)<jupyter_output><empty_output><jupyter_text>Making a product<jupyter_code>from QuantSA.Core.Products.Rates import *

nearDate = Date("2021-09-14")
farDate = Date("2021-12-14")
fra = FRA(1000000, 0.25, 0.07, True, nearDate, farDate, jibar)

print(fra)<jupyter_output><empty_output><jupyter_text>Setting up a model<jupyter_code>from QuantSA.Core.CurvesAndSurfaces import *
from QuantSA.Valuation.Models.Rates import *
from QuantSA.Shared.Primitives import *
from QuantSA.Valuation import *

# Set up the model
valueDate = Date("2020-09-14")
maximumDate = Date("2030-09-14")
dates = [valueDate, maximumDate]
rates = [ 0.07, 0.07 ]
discountCurve = DatesAndRates(zar, valueDate, dates, rates, maximumDate)

numeraireModel = DeterministicCurves(discountCurve);
otherModels = List[Simulator]() # no model other than discounting for now.
coordinator = Coordinator(numeraireModel, otherModels, 1) # the magic ingredient that gets 
                                                          # models and products to work 
                                                          # together

print("A model is ready.")<jupyter_output><empty_output><jupyter_text>Valuing the product with the model<jupyter_code># Run the valuation
portfolio = [fra]

try: 
   value = coordinator.Value(fra, valueDate)
except Exception as e: 
    print(e)<jupyter_output><empty_output><jupyter_text>Aha, this is good.  You can't value a FRA with a discounting model because its cashflow depends on 3 month Jibar and your model does not know anything about 3 month Jibar.With this type of constraint (which is deeply embedded in the library): * You will never work under the wrong numeraire again * You will never use the wrong curve to forecast a rate or asset price * You will never incorrectly combine cashflows in different currencies * etc. For our problem at hand we need to fix the model by setting it up to forecast some rates:<jupyter_code>from QuantSA.Core.MarketData import *

# add a forecast curve
forwardRates = [0.070614, 0.070614]
forecastCurve = ForecastCurve(valueDate, jibar, dates, forwardRates) # use flat 7% rates for forecasting
numeraireModel = DeterministicCurves(discountCurve);
numeraireModel.AddRateForecast(forecastCurve) # add the forecast curve to the model
otherModels = List[Simulator]() # no model other than discounting for now.
coordinator = Coordinator(numeraireModel, otherModels, 1)

# value the product
value = coordinator.Value(fra, valueDate)
print("value is: {:.2f}".format(value))<jupyter_output><empty_output><jupyter_text>Is the value right?<jupyter_code># check the value
import numpy as np

t = (nearDate.value - valueDate.value) / 365.0 # C# operator overloading does not work in Python
dt = 0.25
fixedRate = 0.07
notional = 1000000.0
fwdRate = 0.070614
refValue = (notional * (fwdRate - fixedRate) * dt / (1 + fwdRate * dt) * 
            np.exp(-t * 0.07))

print("value is: {:.2f}.  Expected {:.2f}".format(value, refValue))<jupyter_output><empty_output><jupyter_text>And just like that the cashflow definition can be turned into a value.  Same Product Different ModelIn QuantSA models and products are independent.Here is a demonstration of the same FRA with a Hull White model instead of deterministic curve discounting:<jupyter_code>valueDate = Date(2016, 9, 17)
flatRate = 0.07
newModel = HullWhite1F(zar, 0.05, 0.01, flatRate, flatRate)
# tell HW model it is allowed to make some forecasts
newModel.AddForecast(jibar)  

newCoordinator = Coordinator(newModel, List[Simulator](), 100000)
value = newCoordinator.Value(fra, valueDate)
print("value with the new model is: {:.2f}".format(value))<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.08870116156282999, 'fraction_numerical': 0.022351284758887716, 'mean_word_length': 4.925964546402502, 'pattern_counts': {'":': 0, '<': 33, '<?xml version=': 0, '>': 33, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '8', 'dir': 'jupyter-structured-clean-dedup', 'id': '102518', 'license': 'MIT', 'n_tokens_mistral': 1843, 'n_tokens_neox': 1709, 'n_words': 571, 'path': 'Python/NotebookExample.ipynb', 'repo_name': 'wlpretorius/QuantSA', 'size': '5682'}