Building a COM server

In this section, we are concerned with building the server component of the COM interface. We will first take a look at the prerequisites for building the server components using Python. Then, we will proceed to build an option pricing the COM server using some of the topics we covered in Chapter 4, Numerical Procedures.

Prerequisites

The COM interface is an industry standard by Microsoft; therefore, the following software is required to complete this tutorial:

  • Microsoft Windows XP operating system or later
  • Microsoft Excel 2003 or later
  • Python 2.7 or later with SciPy and NumPy packages
  • The pythoncom module

Getting the pythoncom module

The pythoncom module contains Python extensions for Microsoft Windows. The files are available freely as pywin32 on SourceForge at http://sourceforge.net/projects/pywin32/files/. To download the executable file, navigate to the pywin32 folder, and select the latest available build. Download the installer executable that is compatible with your system. Note that there is one download package for each supported version of Python. Be sure to check for the version of Python installed in your environment and download the corresponding package. Some packages have a 32-bit and a 64-bit version available. You must download the one that corresponds to the Python you have installed. Even if you have a 64-bit computer, if you installed a 32-bit version of Python, you must install the 32-bit version of pywin32.

Once the executable file is downloaded to your hard drive, run the installer, and follow the onscreen instructions to add the pythoncom module to your Python environment.

Building the Black-Scholes model COM server

Let's build a simple COM server using the classic Black-Scholes options pricing model to calculate the theoretical value of a call or a put option. The calculator is implemented as the BlackScholes class with a method named pricer that accepts the current underlying price, strike price, annualized interest rate, time left to maturity in terms of years, volatility of the underlying instrument, and annualized dividend yield as its input parameters. The full COM server code in Python is given as follows:

""" Black-Scholes pricer COM server """
import numpy as np
import scipy.stats as stats
import pythoncom

class BlackScholes:
    _public_methods_ = ["call_pricer", "put_pricer"]
    _reg_progid_ = "BlackScholes.Pricer"
    _reg_clsid_ =  pythoncom.CreateGuid()

    def d1(self, S0, K, r, T, sigma, div):
        return (np.log(S0/K) + ((r-div) + sigma**2 / 2) * T)/ 
               (sigma * np.sqrt(T))

    def d2(self, S0, K, r, T, sigma, div):
        return (np.log(S0 / K) + ((r-div) - sigma**2 / 2) * T) / 
               (sigma * np.sqrt(T))

    def call_pricer(self, S0, K, r, T, sigma, div):
        d1 = self.d1(S0, K, r, T, sigma, div)
        d2 = self.d2(S0, K, r, T, sigma, div)
        return S0 * np.exp(-div * T) * stats.norm.cdf(d1) 
               - K * np.exp(-r * T) * stats.norm.cdf(d2)

    def put_pricer(self, S0, K, r, T, sigma, div):
        d1 = self.d1(S0, K, r, T, sigma, div)
        d2 = self.d2(S0, K, r, T, sigma, div)
        return K * np.exp(-r * T) * stats.norm.cdf(-d2) 
               - S0 * np.exp(-div * T) *stats.norm.cdf(-d1)

if __name__ == "__main__":
    # Run "python binomial_tree_am.py"
    #   to register the COM server.
    # Run "python binomial_tree_am.py --unregister"
    #   to unregister it.
    print "Registering COM server..."
    import win32com.server.register
    win32com.server.register.UseCommandLine(BlackScholes)

Note the use of the three magic variables: _public_methods_, _reg_progid_, and _reg_clsid_ in the COM server object. The _public_methods_ variable defines the methods that are exposed to the COM clients. The _reg_progid_ variable defines the name of the COM server that is called from the COM client. The _reg_clsid_ variable contains the unique class identifier in the registry.

Registering and unregistering the COM server

Assuming that the code is saved in the black_scholes.py file, we can compile the COM server and register with the registry:

$ python black_scholes.py
Registering COM server…
Registered: BlackScholes.Pricer

The COM server is now accessible for COM communications.

To unregister the COM server, the additional --unregister parameter is used:

$ python black_scholes.py --unregister
Registering COM server…
Unregistered: BlackScholes.Pricer

The COM server is now unregistered and cannot be accessed by the COM clients.

Building the Cox-Ross-Rubinstein binomial tree model COM server

In Chapter 4, Numerical Procedures, we looked at several options pricing models. One such model is the Cox-Ross-Rubinstein (CRR) model using a binomial tree. Before we can create a second COM server based on this model, let's copy and paste these class files created earlier, namely, BinomialCRROption.py, BinomialTreeOption.py, and StockOption.py, to our working directory.

Now, let's create our COM server using the BinomialCRRCOMServer class and save it as binomial_crr_com.py:

""" Binomial CRR tree COM server """
from BinomialCRROption import BinomialCRROption
import pythoncom

class BinomialCRRCOMServer:
    _public_methods_ = [ 'pricer']
    _reg_progid_ = "BinomialCRRCOMServer.Pricer"
    _reg_clsid_ = pythoncom.CreateGuid()

    def pricer(self, S0, K, r, T, N, sigma,
               is_call=True, div=0., is_eu=False):
        model = BinomialCRROption(S0, K, r, T, N,
                                  {"sigma": sigma,
                                   "div": div,
                                   "is_call": is_call,
                                   "is_eu": is_eu})
        return model.price()

if __name__ == "__main__":
    print "Registering COM server..."
    import win32com.server.register
    win32com.server.register.UseCommandLine(BinomialCRRCOMServer)

Similar to our Black-Scholes COM server, here the pricer method creates an instance of the BinomialCRROption class and returns the calculated price from the CRR binomial tree model.

Building the trinomial lattice model COM server

In Chapter 4, Numerical Procedures, we also explored the use of a trinomial lattice in options pricing. Let's use this model as our third COM server. Let's copy and paste the related class files, namely, TrinomialLattice.py and TrinomialTreeOption.py, to our working directory.

Create our COM server with the TrinomialLatticeCOMServer class and save it as trinomial_lattice_com.py:

""" Trinomial Lattice COM server """
from TrinomialLattice import TrinomialLattice
import pythoncom

class TrinomialLatticeCOMServer:
    _public_methods_ = ['pricer']
    _reg_progid_ = "TrinomialLatticeCOMServer.Pricer"
    _reg_clsid_ = pythoncom.CreateGuid()

    def pricer(self, S0, K, r, T, N, sigma,
               is_call=True, div=0., is_eu=False):
        model = TrinomialLattice(S0, K, r, T, N,
                                 {"sigma": sigma,
                                  "div": div,
                                  "is_call": is_call,
                                  "is_eu": is_eu})
        return model.price()

if __name__ == "__main__":
    print "Registering COM server..."
    import win32com.server.register
    win32com.server.register.UseCommandLine(TrinomialLatticeCOMServer) 

Now, let's build and register our three COM server Python files with the registry:

$ python black_scholes.py
Registering COM server…
Registered: BlackScholes.Pricer

$ python binomial_crr_com.py
Registering COM server…
Registered: BinomialCRRCOMServer.Pricer

$ python trinomial_lattice_com.py
Registering COM server…
Registered: TrinomialLatticeCOMServer.Pricer

With our COM server components successfully registered with the registry, we can now proceed to create our COM client in Excel in the next section.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset