Skip to content


The QuantLib Ruby Project, Part 2


I. Overview

Part 2 of this project presents a Ruby on Rails implementation of a QuantLib web application for pricing American options. This builds on the QuantLib Ruby server created in Part 1. Click anywhere on the image below to view the web application.

Ray's QuantLib Ruby Project


II. Consulting

I do my best to explain the concepts and techniques behind my projects. If you like my work and can use my expertise in your projects, I am available for consulting at a competitive rate.


III. Procedure

1. Create the Rails Project and MVC

a.) Create the Rails Project
Using a terminal window on the QuantLib Ruby server, create the Rails project as follows:

$ rails RayQuantLib
$ cd RayQuantLib

A Rails application uses the Model-View-Controller (MVC) framework, which separates an application’s data (model), user interface (view), and business/control logic (controller) into three distinct components.

b.) Create the MySQL Database

Create a new username and 3 databases for development, test, and production, as required by the Rails framework.

$ mysql -u root -p <password>
mysql> create user <username>;
mysql> set password for <username> = password(“<password>”);
mysql> create database RayQuantLib_dev;
mysql> grant all on RayQuantLib_dev.* to <username>@localhost identified by ‘<password>’;
mysql> create database RayQuantLib_test;
mysql> grant all on RayQuantLib_test.* to <username>@localhost identified by ‘<password>’;
mysql> create database RayQuantLib_prod;
mysql> grant all on RayQuantLib_prod.* to <username>@localhost identified by ‘<password>’;

Modify the database.yml file to use the following database configuration for development: test: and production:
  RayQuantLib/config/database.yml

development:
   adapter: mysql
   database: RayQuantLib_dev
   username: <username>
   password: <password>

test:
   adapter: mysql
   database: RayQuantLib_test
   username: <username>
   password: <password>

production:
   adapter: mysql
   database: RayQuantLib_prod
   username: <username>
   password: <password>

c.) Create the Model

Create a Model named “AmericanOption” and perform the initial database migration as follows:

$ ruby script/generate model AmericanOption
$ rake db:migrate

d.) Create the Controller and View

Create a Controller and View named “AmericanOption” as follows:

$ ruby script/generate controller AmericanOption index

Declare this resource by adding the following line to:
  RayQuantLib/config/routes.rb

map.resources :AmericanOption



2. Create the Application Layout View

Create the following file for the XHTML application layout. This layout is displayed at the beginning of every web page in the application, and the “yield” function passes control to the appropriate Controller.

  RayQuantLib/app/views/layouts/application.html.erb

<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Strict//EN”
“http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd”>
<html xmlns=”http://www.w3.org/1999/xhtml” xml:lang=”en” lang=”en”>
   <head>
     <meta http-equiv=”Content-type” content=”text/html; charset=utf-8″ />
     <title>Ray’s QuantLib Ruby Project</title>
     <%= stylesheet_link_tag ‘style’ %>
   </head>
   <body>
     <div id=”content”>
     <h2>Ray’s QuantLib Ruby Project</h2>
     <%= yield %>
     </div>
   </body>
</html>

Create the CSS file referenced in application layout:
  RayQuantLib/public/stylesheets/style.css

3. Create the Input Form View

Create the input form for “Pricing American Options” in the following file. The sample code below shows some design patterns for creating a form, listbox, date, and textbox in Ruby on Rails:

  RayQuantLib/app/views/american_option/index.html.erb

<% form_tag(‘/american_option’) do -%>
   <% field_set_tag nil, :class => ‘form_fieldset’ do %>

     <p>
     <span class=”form_label”>Option Type:</span>
     <%= select_tag :optionType, options_for_select([["Call Option","0"],
            ["Put Option","1"]], @optionType.to_s) %>
     </p>

     <p>
     <span class=”form_label”>Exercise Date:</span>
     <%= date_select(‘range’, ‘exerciseDate’,
             :order => [:month, :day, :year], :use_short_month => true,
             :default => @exerciseDate) %>
     <span class=”form_error”><%= @exerciseDate_error %></span>
     </p>

     <p>
     <span class=”form_label”>Volatility (%):</span>
     <span><%= text_field_tag ‘volatility’, @volatility.to_s,
            :size => 4, :maxlength => 4 %&gt</span>
     <span class=”form_error”><%= @volatility_error %></span>
     </p>

   <% end %>
<% end -%>

Rather than building the form directly with XHTML tags, the Rails form_tag helper is used here to defend against Cross-Site Request Forgery (CSRF) attacks via the unique authenticity_token which Rails generates for each form session.

4. Process Form Input in the Controller

In a Rails application, the Controller is responsible for handling business logic and passing variables between the Model and the View. The sample Ruby code below, which is entered within the index function (def index), shows some design patterns for retrieving the values entered in the Input Form.

  RayQuantLib/app/controllers/american_option_controller.rb

if( params[:optionType].nil? )
   @optionType = 0 # default to “Call Option”
else
   @optionType = params[:optionType].to_i
end

if( params[:range].nil? )
   # initialize form parameters
   @exerciseDate = Date.today.next_year()     # set date in Ruby
   ex_daysfromtoday = (@exerciseDate – Date.today).to_i
   exerciseDate = QuantLib::Date.todaysDate() + ex_daysfromtoday     # set date in QuantLib
else
   # process form fields
   @exerciseDate = Date.civil(params[:range][:"exerciseDate(1i)"].to_i,
               params[:range][:"exerciseDate(2i)"].to_i,
               params[:range][:"exerciseDate(3i)"].to_i)
end

The sample Ruby code below is used for input form validation:

if( @exerciseDate < @settlementDate )
   @exerciseDate_error = '* Exercise Date must be greater or equal to Settlement Date'
   form_error = true
else
   @exerciseDate_error = ''
end

if( @volatility < 0 or @volatility > 100 )
   @volatility_error = ‘* Volatility must be between 0 and 100′
   form_error = true
else
   @volatility_error = ”
end

if( form_error )
   return
end



5. Process QuantLib Calculations in the Controller

To enable QuantLib, the following lines must be entered at the top of the Controller file:
  RayQuantLib/app/controllers/american_option_controller.rb

require ‘QuantLib’
include QuantLib

The sample code below shows how to call QuantLib functions within Ruby on Rails. The QuantLib-SWIG interface library (installed in Part 1) allows us to call QuantLib C++ functions as if they were Ruby functions.

riskFreeRate = FlatForward.new(settlementDate, (@riskFreeRate/100.0), Actual365Fixed.new)
exercise = AmericanExercise.new(settlementDate, exerciseDate)
if( @optionType == 0 )
   payoff = PlainVanillaPayoff.new(Option::Call, @strikePrice)
else
   payoff = PlainVanillaPayoff.new(Option::Put, @strikePrice)
end
underlying = SimpleQuote.new(@underlyingPrice)
volatility = BlackConstantVol.new(valuationDate, TARGET.new,
    (@volatility/100.0), Actual365Fixed.new)
dividendYield = FlatForward.new(settlementDate, (@dividendYield/100.0), Actual365Fixed.new)
process = BlackScholesMertonProcess.new(
     QuoteHandle.new(underlying),
     YieldTermStructureHandle.new(dividendYield),
     YieldTermStructureHandle.new(riskFreeRate),
     BlackVolTermStructureHandle.new(volatility))
option = VanillaOption.new(payoff, exercise)



6. Display Controller Output to the View

The sample Ruby code below displays the output by populating the @output variable, which is passed back to the View.

# method: analytic
option.pricingEngine = BaroneAdesiWhaleyEngine.new(process)
report(‘Barone-Adesi-Whaley’, option.NPV)
option.pricingEngine = BjerksundStenslandEngine.new(process)
report(‘Bjerksund-Stensland’,option.NPV)

# method: finite differences
timeSteps = 801
gridPoints = 800
option.pricingEngine = FDAmericanEngine.new(process,timeSteps,gridPoints)
report(‘finite differences’,option.NPV)

# method: binomial
timeSteps = 801
option.pricingEngine = BinomialVanillaEngine.new(process,’jr’,timeSteps)
report(‘binomial (JR)’,option.NPV)
option.pricingEngine = BinomialVanillaEngine.new(process,’crr’,timeSteps)
report(‘binomial (CRR)’,option.NPV)

The output code above makes use of the following helper function in the Controller:
  RayQuantLib/app/controllers/american_option_controller.rb

def report(method, npv)
   npv = sprintf(‘%.5f’, npv)
   @output = @output + ‘<div>’
   @output = @output + ‘<span class=”output_method”>’ + method + ‘</span>’
   @output = @output + ‘<span class=”output_npv”>’ + npv + ‘</span>’
   @output = @output + ‘</div>’
end

Finally, the following code displays the output in our View:

  RayQuantLib/app/views/american_option/index.html.erb

<%= @output %>




IV. Future Enhancements

1. QuantLib Functionality

Additional QuantLib features can be developed in the future, including dynamic hedging, swap valuation, bond pricing, and Monte Carlo simulation.

2. QuantLib Documentation

A more detailed explanation of the QuantLib functions and design patterns used in this project can be added in the future. In the meantime, the official QuantLib documentation can be found in the references below.


V. References

1. QuantLib Reference Manual
http://quantlib.org/reference/modules.html

2. Rails Framework Documentation
http://api.rubyonrails.org/




0 Responses

Stay in touch with the conversation, subscribe to the RSS feed for comments on this post.

Some HTML is OK

(required)

(required, but never shared)

or, reply to this post via trackback.