Monday, May 22, 2017

Android Studio 3.0 Canary with Kotlin

Peamon Calculator, java source code converted to Kotlin
Modifications to the following files are needed for Android Studio 3.0

app/build.gradle    Select all
apply plugin: 'com.android.application' apply plugin: 'kotlin-android' android { compileSdkVersion 23 buildToolsVersion '26.0.0 rc2' // for Android Studio 3.0 defaultConfig { applicationId "com.example.peamoncalculator" minSdkVersion 22 targetSdkVersion 23 versionCode 1 versionName "1.0" archivesBaseName = "PeamonCalculator" + versionName testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } } dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) compile 'com.android.support:appcompat-v7:23+' compile 'com.android.support.constraint:constraint-layout:1.0.2' compile 'com.android.support:design:23+' // Required for local unit tests testCompile 'junit:junit:4.12' // Required for instrumented tests androidTestCompile 'com.android.support.test.espresso:espresso-core:2.2.2' androidTestCompile 'com.android.support.test:runner:0.5' androidTestCompile 'com.android.support:support-annotations:23+' compile "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version" } repositories { mavenCentral() } // add these tasks in run config to make kotlin test working // for junit task copyTestClasses(type: Copy) { from "build/tmp/kotlin-classes/debugUnitTest" into "build/intermediates/classes/debug" } // for instrumented test task copySdkClasses(type: Copy) { from "build/tmp/kotlin-classes/debug" into "build/intermediates/classes/debug" } afterEvaluate { compileDebugUnitTestSources.dependsOn copyTestClasses compileReleaseUnitTestSources.dependsOn copyTestClasses compileDebugAndroidTestSources.dependsOn copySdkClasses }




gradle-wrapper.properties    Select all
distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists distributionUrl=https\://services.gradle.org/distributions/gradle-4.0-milestone-1-all.zip



Project/build.gradle    Select all
// Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { ext.kotlin_version = '1.1.2-4' repositories { maven { url 'https://maven.google.com' } jcenter() } dependencies { classpath 'com.android.tools.build:gradle:3.0.0-alpha1' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files } } allprojects { repositories { jcenter() maven { url 'https://maven.google.com' } mavenCentral() } } task clean(type: Delete) { delete rootProject.buildDir }



app/src/main/java/com/example/peamoncalculator/MainActivity.kt    Select all
// Converted to Kotlin for Android Studio 3.0 package com.example.peamoncalculator import android.app.Activity import android.os.Bundle import android.support.design.widget.FloatingActionButton import android.support.design.widget.Snackbar import android.support.v7.app.AppCompatActivity import android.support.v7.widget.Toolbar import android.view.View import android.view.Menu import android.view.MenuItem import android.view.View.OnClickListener import android.widget.Button import android.widget.EditText import android.widget.TextView class MainActivity : Activity(), OnClickListener { private var Scr: EditText? = null // textbox screen private val debugScr: EditText? = null // debug screen private var NumberBf: Float = 0.toFloat() //save screen before pressing button operation; private var Operation = "" private var LastOperation = "" override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) Scr = findViewById(R.id.editText) as EditText println("OK Calculator") // set debug screen text val idList = intArrayOf(R.id.button1, R.id.button2, R.id.button3, R.id.button4, R.id.button5, R.id.button6, R.id.button7, R.id.button8, R.id.button9, R.id.button0, R.id.buttonAdd, R.id.buttonSub, R.id.buttonMul, R.id.buttonDiv, R.id.buttonDot, R.id.buttonEq) for (id in idList) { val v = findViewById(id) v.setOnClickListener(this) println("It comes here " + (v as Button).text.toString()) } } // Have to implement with the OnClickListner // onClick is called when a view has been clicked. override fun onClick(v: View) { // Parameter v stands for the view that was clicked. println("Pressed Button " + (v as Button).text.toString()) val eqButton = findViewById(R.id.buttonEq) as Button eqButton.text = "=" when (v.id) { R.id.buttonAdd -> { sMath("+") LastOperation = "+" } R.id.buttonSub -> { sMath("-") LastOperation = "-" } R.id.buttonMul -> { sMath("*") LastOperation = "*" } R.id.buttonDiv -> { sMath("/") LastOperation = "/" } R.id.buttonEq -> { if (LastOperation == "=") { Scr!!.setText("0") NumberBf = 0f Operation = "" LastOperation = "=" //break } LastOperation = "=" eqButton.text = "C" sResult() } else -> { val numb = (v as Button).text.toString() getKeyboard(numb) } } } fun sMath(str: String) { NumberBf = java.lang.Float.parseFloat(Scr!!.text.toString()) // save the screen Operation = str // save operation Scr!!.setText("0") // clear screen } fun getKeyboard(str: String) { var ScrCurrent = Scr!!.text.toString() if (ScrCurrent == "0") ScrCurrent = "" if (ScrCurrent.contains(".") and (str == ".")) return ScrCurrent += str Scr!!.setText(ScrCurrent) } fun sResult() { val NumberAf = java.lang.Float.parseFloat(Scr!!.text.toString()) var result = 0f if (Operation == "+") { result = NumberBf + NumberAf } if (Operation == "-") { result = NumberBf - NumberAf } if (Operation == "*") { result = NumberBf * NumberAf } if (Operation == "/") { result = NumberBf / NumberAf } Scr!!.setText(result.toString()) } override fun onCreateOptionsMenu(menu: Menu): Boolean { // Inflate the menu; this adds items to the action bar if it is present. menuInflater.inflate(R.menu.menu, menu) return true } override fun onOptionsItemSelected(item: MenuItem): Boolean { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. val id = item.itemId if (id == R.id.action_settings) { println("Settings") return true } return super.onOptionsItemSelected(item) } }



app/src/main/res/layout/activity_main.xml    Select all
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" tools:context="com.example.peamoncalculator.MainActivity" > <EditText android:text="0" android:id="@+id/editText" android:layout_width="fill_parent" android:layout_height="fill_parent" android:maxLength="12" android:textSize="50sp" android:layout_weight="0.6" android:gravity="right" android:hint="0"> </EditText> <TableLayout android:id="@+id/tableLayout1" android:layout_height="fill_parent" android:layout_width="fill_parent" android:layout_weight="0.2"> <TableRow android:id="@+id/tableRow1" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_weight="0.25"> <Button android:text="1" android:id="@+id/button1" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_weight="0.25" android:textSize="30sp"></Button> <Button android:text="2" android:id="@+id/button2" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_weight="0.25" android:textSize="30sp"></Button> <Button android:text="3" android:id="@+id/button3" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_weight="0.25" android:textSize="30sp"></Button> <Button android:text="4" android:id="@+id/button4" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_weight="0.25" android:textSize="30sp"></Button> </TableRow> <TableRow android:id="@+id/tableRow2" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_weight="0.25"> <Button android:text="5" android:id="@+id/button5" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_weight="0.25" android:textSize="30sp"></Button> <Button android:text="6" android:id="@+id/button6" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_weight="0.25" android:textSize="30sp"></Button> <Button android:text="7" android:id="@+id/button7" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_weight="0.25" android:textSize="30sp"></Button> <Button android:text="8" android:id="@+id/button8" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_weight="0.25" android:textSize="30sp"></Button> </TableRow> <TableRow android:id="@+id/tableRow3" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_weight="0.25"> <Button android:text="9" android:id="@+id/button9" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_weight="0.25" android:textSize="30sp"></Button> <Button android:text="0" android:id="@+id/button0" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_weight="0.25" android:textSize="30sp"></Button> <Button android:text="." android:id="@+id/buttonDot" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_weight="0.25" android:textSize="30sp"></Button> <Button android:text="=" android:id="@+id/buttonEq" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_weight="0.25" android:textSize="30sp"></Button> </TableRow> <TableRow android:id="@+id/tableRow4" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_weight="0.25"> <Button android:text="+" android:background="#8FCC8F" android:id="@+id/buttonAdd" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_weight="0.25" android:textSize="30sp"></Button> <Button android:text="-" android:background="#8FBC8F" android:id="@+id/buttonSub" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_weight="0.25" android:textSize="30sp"></Button> <Button android:text="*" android:background="#8FCC8F" android:id="@+id/buttonMul" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_weight="0.25" android:textSize="30sp"></Button> <Button android:text="/" android:background="#8FBC8F" android:id="@+id/buttonDiv" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_weight="0.25" android:textSize="30sp"></Button> </TableRow> </TableLayout> </LinearLayout>





C++ Example

The original HelloDroid project file for Android 1.3 is from https://mega.nz/#!iwoHjDiC!dJ45TLYAmCoUYnSOE9H1faYYOSyt5FxfBnmlXeqIRgU

Modifications to the following files are needed for Android Studio 3.0

app/build.gradle    Select all
apply plugin: 'com.android.application' android { compileSdkVersion 23 buildToolsVersion '25.0.2' // minimum 25.0.x for Android Studio 3.0 defaultConfig { applicationId 'com.beginndkgamecode.hellodroid' minSdkVersion 9 targetSdkVersion 23 versionCode 1 versionName "1.0" archivesBaseName = 'HELLODRIOD_' + versionName ndk { abiFilters 'armeabi-v7a', 'x86', 'x86_64' } externalNativeBuild { ndkBuild { arguments "NDK_APPLICATION_MK=src/main/jni/Application.mk", "-j6" } } } buildTypes { debug { minifyEnabled false zipAlignEnabled true debuggable true useProguard false } release { minifyEnabled false zipAlignEnabled true useProguard true proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } externalNativeBuild { ndkBuild { path "src/main/jni/Android.mk" } } } dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) compile 'com.android.support:appcompat-v7:23+' compile 'com.android.support.constraint:constraint-layout:1.0.0+' }

app/src/main/jni/Application.mk    Select all
APP_PLATFORM := android-9 APP_ABI := armeabi-v7a x86 x86_64

Project:HelloDroid/build.gradle    Select all
// Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { repositories { jcenter() } dependencies { //classpath 'com.android.tools.build:gradle-experimental:0.7.0-beta1' //classpath 'com.android.tools.build:gradle:2.2.0-alpha3' //updated classpath for Android Studio 3.0 classpath 'com.android.tools.build:gradle:3.0.0-alpha1' } } allprojects { repositories { jcenter() } }



gradle-wrapper.properties    Select all
distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists #updated to gradle-4.0-milestone-1-all.zip for Android Studio 3.0 distributionUrl=https\://services.gradle.org/distributions/gradle-4.0-milestone-1-all.zip



app/src/main/jni/Android.mk    Select all
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := hellodroid LOCAL_SRC_FILES := main.cpp LOCAL_LDLIBS := -llog -landroid -lEGL -lGLESv2 LOCAL_STATIC_LIBRARIES := android_native_app_glue include $(BUILD_SHARED_LIBRARY) $(call import-module,android/native_app_glue)



ATTENTION: Quit Docker (if running) before launching Android Emulator in HAXM.






Install kotlin compiler in macOS


shell script     Select all
# install kotlin in macOS, also applicable to Ubuntu Linux # for Ubuntu, sdk install java curl -s https://get.sdkman.io | bash # open another Terminal sdk install kotlin # create hello.kt cat > hello.kt <<"EOF" fun main(args: Array<String>) { println("Hello, World!") val list = listOf(1, 3, 5, 7) for (k in list) { println("k is $k") } list.forEach(fun(x) { println("x is $x") }) args.forEachIndexed(fun(x, y) { println("arg[$x] is $y") }) } EOF # compile and test hello.kt kotlinc hello.kt -include-runtime -d hello.jar java -jar hello.jar a b c d



Friday, May 5, 2017

How to translate QuantLib C++ code to Python

Here is a demo of how QuantLib c++ code are translated to Python. This included the code for importing of csv file and construction of volatility surface and the timing of MCDiscreteArithmeticAPEngine. Slicing and manipulation of list/array is much easier in Python than that of C++ code. However, C++ is faster.

QuantLib C++ source code, AsianOption.cpp

AsianOption.cpp    Select all
// g++ -std=c++11 AsianOption.cpp -o AsianOption -lQuantLib #include <ql/quantlib.hpp> #include <boost/timer.hpp> #include <iostream> #include <iomanip> #include <fstream> #include <string> #include <boost/algorithm/string/split.hpp> #include <boost/algorithm/string/classification.hpp> #include <boost/lexical_cast.hpp> using namespace QuantLib; using namespace std; void GetStrikes(string &path, vector<Real> &strikes) { std::ifstream file(path); std::string line; std::vector<std::string> tokens; int linecount = 0; while (std::getline(file, line)) { std::stringstream stringStream(line); std::string content; int item = 0; if (linecount >= 1) while (std::getline(stringStream, content, ',')) { switch (item) { case 0: // strikes are on first column only strikes.push_back(boost::lexical_cast<double>(content)); break; default: break; } item++; } linecount++; } return; /* if hardcode csv data strikes.push_back(0.67263); strikes.push_back(0.71865); strikes.push_back(0.7487); strikes.push_back(0.77129); strikes.push_back(0.78984); strikes.push_back(0.80587); strikes.push_back(0.82034); strikes.push_back(0.83379); strikes.push_back(0.84658); strikes.push_back(0.85792); strikes.push_back(0.87354); strikes.push_back(0.89085); strikes.push_back(0.90904); strikes.push_back(0.9289); strikes.push_back(0.95157); strikes.push_back(0.97862); strikes.push_back(1.01337); strikes.push_back(1.06261); strikes.push_back(1.14631); */ } void GetExpiryDates(string &path, vector<Date> &expirations) { std::ifstream file(path); std::string line; std::vector<std::string> tokens; int linecount = 0; while (std::getline(file, line)) { std::stringstream stringStream(line); std::string content; int item = 0; if (linecount == 0) // expiration dates are on first row only while (std::getline(stringStream, content, ',')) { switch (item) { case 1: case 2: case 3: case 4: boost::algorithm::split(tokens, content, boost::algorithm::is_any_of("/")); expirations.push_back(Date(Day(boost::lexical_cast<int>(tokens.at(1))), Month(boost::lexical_cast<int>(tokens.at(0))), Year(boost::lexical_cast<int>(tokens.at(2))))); break; default: break; } item++; } linecount++; } return; /* if hardcode csv data expirations.push_back(Date(27, June, 2017)); expirations.push_back(Date(27, September, 2017)); expirations.push_back(Date(27, December, 2017)); expirations.push_back(Date(27, June, 2018)); */ } Matrix GetVolData(string &path, vector<Date> &expirations, vector<Real> &strikes) { // Matrix volMatrix(19, 4); Matrix volMatrix(strikes.size(), expirations.size()); std::ifstream file(path); std::string line; std::vector<std::string> tokens; int linecount = 0; while (std::getline(file, line)) { std::stringstream stringStream(line); std::string content; int item = 0; if (linecount >= 1) // vols are on second row onward while (std::getline(stringStream, content, ',')) { switch (item) { case 1: case 2: case 3: case 4: volMatrix[linecount-1][item-1] = boost::lexical_cast<double>(content); // vols are on second column onward break; default: break; } item++; } linecount++; } return volMatrix; /* if hardcode csv data //0.67263,0.144183920277296,0.139374695503699,0.135526204819277,0.12885 volMatrix[0][0] = 0.144183920277296; volMatrix[0][1] = 0.139374695503699; volMatrix[0][2] = 0.135526204819277; volMatrix[0][3] = 0.12885; //0.71865,0.133703802426343,0.129893056346044,0.126909006024096,0.12175 volMatrix[1][0] = 0.133703802426343; volMatrix[1][1] = 0.129893056346044; volMatrix[1][2] = 0.126909006024096; volMatrix[1][3] = 0.12175; //0.7487,0.126860526863085,0.123701764371087,0.121209416342412,0.11695 volMatrix[2][0] = 0.126860526863085; volMatrix[2][1] = 0.123701764371087; volMatrix[2][2] = 0.121209416342412; volMatrix[2][3] = 0.11695; // 0.77129,0.121720863192182,0.118881707209199,0.116979766476388,0.11381 volMatrix[3][0] = 0.121720863192182; volMatrix[3][1] = 0.118881707209199; volMatrix[3][2] = 0.116979766476388; volMatrix[3][3] = 0.11381; // 0.78984,0.117581136690647,0.115218428824572,0.113899219047619,0.11163 volMatrix[4][0] = 0.117581136690647; volMatrix[4][1] = 0.115218428824572; volMatrix[4][2] = 0.113899219047619; volMatrix[4][3] = 0.11163; // 0.80587,0.114363421052632,0.112523118729097,0.111637193240265,0.11019 volMatrix[5][0] = 0.114363421052632; volMatrix[5][1] = 0.112523118729097; volMatrix[5][2] = 0.111637193240265; volMatrix[5][3] = 0.11019; //0.82034,0.111728795180723,0.110489402985075,0.109987692307692,0.10921 volMatrix[6][0] = 0.111728795180723; volMatrix[6][1] = 0.110489402985075; volMatrix[6][2] = 0.109987692307692; volMatrix[6][3] = 0.10921; // 0.83379,0.109805703883495,0.109100413723512,0.108870460584588,0.1086 volMatrix[7][0] = 0.109805703883495; volMatrix[7][1] = 0.109100413723512; volMatrix[7][2] = 0.108870460584588; volMatrix[7][3] = 0.1086; // 0.84658,0.108581646586345,0.108250493273543,0.108197213114754,0.10829 volMatrix[8][0] = 0.108581646586345; volMatrix[8][1] = 0.108250493273543; volMatrix[8][2] = 0.108197213114754; volMatrix[8][3] = 0.10829; // 0.85792,0.108190964125561,0.107986172506739,0.10796631037213,0.10822 volMatrix[9][0] = 0.108190964125561; volMatrix[9][1] = 0.107986172506739; volMatrix[9][2] = 0.10796631037213; volMatrix[9][3] = 0.10822; // 0.87354,0.10859510460251,0.108310304612707,0.108232350773766,0.10849 volMatrix[10][0] = 0.10859510460251; volMatrix[10][1] = 0.108310304612707; volMatrix[10][2] = 0.108232350773766; volMatrix[10][3] = 0.10849; // 0.89085,0.110043016488846,0.109404567049808,0.109102906403941,0.10919 volMatrix[11][0] = 0.110043016488846; volMatrix[11][1] = 0.109404567049808; volMatrix[11][2] = 0.109102906403941; volMatrix[11][3] = 0.10919; // 0.90904,0.112447321958457,0.111343238289206,0.110615417475728,0.11036 volMatrix[12][0] = 0.112447321958457; volMatrix[12][1] = 0.111343238289206; volMatrix[12][2] = 0.110615417475728; volMatrix[12][3] = 0.11036; // 0.9289,0.115567066189624,0.113888152866242,0.112830993150685,0.11201 volMatrix[13][0] = 0.115567066189624; volMatrix[13][1] = 0.113888152866242; volMatrix[13][2] = 0.112830993150685; volMatrix[13][3] = 0.11201; // 0.95157,0.119454321849106,0.117151688909342,0.115569047072331,0.11433 volMatrix[14][0] = 0.119454321849106; volMatrix[14][1] = 0.117151688909342; volMatrix[14][2] = 0.115569047072331; volMatrix[14][3] = 0.11433; // 0.97862,0.123858310308183,0.121275916334661,0.119199029605263,0.11731 volMatrix[15][0] = 0.123858310308183; volMatrix[15][1] = 0.121275916334661; volMatrix[15][2] = 0.119199029605263; volMatrix[15][3] = 0.11731; // 1.01337,0.129434558979809,0.126231870274572,0.123929902439024,0.12145 volMatrix[16][0] = 0.129434558979809; volMatrix[16][1] = 0.126231870274572; volMatrix[16][2] = 0.123929902439024; volMatrix[16][3] = 0.12145; // 1.06261,0.137335982996812,0.133099606048548,0.12994278699187,0.12723 volMatrix[17][0] = 0.137335982996812; volMatrix[17][1] = 0.133099606048548; volMatrix[17][2] = 0.12994278699187; volMatrix[17][3] = 0.12723; // 1.14631,0.150767120085016,0.144773641066454,0.140163713821138,0.13547 volMatrix[18][0] = 0.150767120085016; volMatrix[18][1] = 0.144773641066454; volMatrix[18][2] = 0.140163713821138; volMatrix[18][3] = 0.13547; return volMatrix; */ } void asian() { // Calendar set up Calendar calendar = TARGET(); Date todaysDate(4, April, 2017); Settings::instance().evaluationDate() = todaysDate; DayCounter dayCounter = Actual360(); // Option parameters Asian FX Option::Type optionType(Option::Call); Average::Type averageType = Average::Arithmetic; Date maturity(4, April, 2018); Real strike = 0.74; Volatility volatility = 0.07053702474; Date obsStart(4, March, 2018); Real runningSum = 0; Size pastFixings = 0; vector<Date> fixingDates; for (Date incrementedDate = obsStart; incrementedDate <= maturity; incrementedDate += 1) { if (calendar.isBusinessDay(incrementedDate)) { fixingDates.push_back(incrementedDate); } } // Option parameters // European Exercise boost::shared_ptr<Exercise> europeanExercise( new EuropeanExercise(maturity)); // Payoff boost::shared_ptr<StrikedTypePayoff> payoffAsianOption( new PlainVanillaPayoff(Option::Type(optionType), strike)); // Model parameters Real underlying = 0.748571186; Spread dividendYield = 0.04125; Rate riskFreeRate = 0.0225377; // Market Data // Quote handling Handle<Quote> underlyingH( boost::shared_ptr<Quote>(new SimpleQuote(underlying))); // Yield term structure handling Handle<YieldTermStructure> flatTermStructure( boost::shared_ptr<YieldTermStructure>(new FlatForward(todaysDate, dividendYield, dayCounter))); // Dividend term structure handling Handle<YieldTermStructure> flatDividendTermStructure( boost::shared_ptr<YieldTermStructure>(new FlatForward(todaysDate, riskFreeRate, dayCounter))); // Volatility structure handling: constant volatility Handle<BlackVolTermStructure> flatVolTermStructure( boost::shared_ptr<BlackVolTermStructure>(new BlackConstantVol(todaysDate, calendar, volatility, dayCounter))); // Read csv file string path = "./VolMatrixA.csv"; vector<Real> strikes = {}; GetStrikes(path, strikes); vector<Date> expirations = {}; GetExpiryDates(path, expirations); cout << "strikes.size() " << strikes.size() << endl; cout << "expirations.size() " << expirations.size() << endl; // assert csv data BOOST_ASSERT_MSG(strikes.size() > 0, static_cast<std::stringstream&>(std::stringstream() << "No valid strikes.size() found! It is " << strikes.size()).str().c_str()); BOOST_ASSERT_MSG(expirations.size() > 0, static_cast<std::stringstream&>(std::stringstream() << "No valid expirations.size() found! It is " << expirations.size()).str().c_str()); Matrix volMatrix = GetVolData(path, expirations, strikes); // Volatility Surface BlackVarianceSurface volatilitySurface(Settings::instance().evaluationDate(), calendar, expirations, strikes, volMatrix, dayCounter); volatilitySurface.setInterpolation<Bicubic>(); volatilitySurface.enableExtrapolation(true); const boost::shared_ptr<BlackVarianceSurface> volatilitySurfaceH( new BlackVarianceSurface(volatilitySurface)); Handle<BlackVolTermStructure> volTermStructure(volatilitySurfaceH); // the BS equation behind boost::shared_ptr<BlackScholesMertonProcess> bsmProcess( new BlackScholesMertonProcess(underlyingH, flatDividendTermStructure, flatTermStructure, volTermStructure)); // Options DiscreteAveragingAsianOption discreteArithmeticAsianAverageOption( averageType, runningSum, pastFixings, fixingDates, payoffAsianOption, europeanExercise); // Outputting on the screen cout << "Option type = " << optionType << endl; cout << "Option maturity = " << maturity << endl; cout << "Underlying = " << underlying << endl; cout << "Strike = " << strike << endl; cout << "Risk-free interest rate = " << setprecision(4) << io::rate(riskFreeRate) << endl; cout << "Dividend yield = " << setprecision(4) << io::rate(dividendYield) << endl; cout << "Volatility = " << setprecision(4) << io::volatility(volatility) << endl; cout << "Time-length between successive fixings = weekly time step" << endl; cout << "Previous fixings = " << pastFixings << endl; cout << setprecision(10) << endl; boost::timer timer; // Pricing engine discreteArithmeticAsianAverageOption.setPricingEngine( boost::shared_ptr<PricingEngine>( MakeMCDiscreteArithmeticAPEngine<LowDiscrepancy>(bsmProcess) .withSamples(1500))); // Timer timer.restart(); try { cout << "Discrete ArithMC Price: " << discreteArithmeticAsianAverageOption.NPV() << endl; } catch (exception const& e) { cout << "Erreur: " << e.what() << endl; } cout << " in " << timer.elapsed() << " s" << endl; timer.restart(); } int main(int, char* []) { asian(); }


QuantLib Python source code, AsianOption.py

AsianOption.py    Select all
#!python2 #!/usr/bin/env python # AsianOption.py from QuantLib import * import csv import time # Calendar set up calendar = TARGET() todaysDate = Date(4, April, 2017) Settings.instance().evaluationDate = todaysDate dayCounter = Actual360() # Option parameters Asian FX optionType = Option.Call averageType = Average.Arithmetic maturity = Date(4, April, 2018) strike = 0.74 volatility = 0.07053702474 obsStart = Date(4, March, 2018) runningSum = 0 pastFixings = 0 fixingDates = [ Date(serial) for serial in range(obsStart.serialNumber(), maturity.serialNumber()) if calendar.isBusinessDay(Date(serial)) ] # Model parameters underlying = 0.748571186 dividendYield = 0.04125 riskFreeRate = 0.0225377 #settlementDate = todaysDate # Option parameters # European Exercise europeanExercise = EuropeanExercise(maturity) # Payoff payoffAsianOption = PlainVanillaPayoff(optionType, strike) # Market Data # Quote handling underlyingH = QuoteHandle(SimpleQuote(underlying)) # Yield term structure handling flatTermStructure = YieldTermStructureHandle(FlatForward(todaysDate, dividendYield, dayCounter)) # Dividend term structure handling flatDividendTermStructure = YieldTermStructureHandle(FlatForward(todaysDate, riskFreeRate, dayCounter)) # Volatility structure handling: constant volatility flatVolTermStructure = BlackVolTermStructureHandle(BlackConstantVol(Settings.instance().evaluationDate, calendar, volatility, dayCounter)) # Read csv file with open('VolMatrixA.csv', 'rb') as f: reader = csv.reader(f) csv_list = list(reader) expirations = [ Date(int(col.split("/")[1]), int(col.split("/")[0]), int(col.split("/")[2])) for col in csv_list[0][1:] ] # expirations are on first row[0] and for second column[1:] onward strikes = [ float(row[0]) for row in csv_list[1:] ] # strikes are for second row [1:] onward and on first column [0] """ # if hardcode csv data expirations = [Date(27, June, 2017), Date(27, September, 2017), Date(27, December, 2017), Date(27, June, 2018)] strikes = [0.67263, 0.71865, 0.7487, 0.77129, 0.78984, 0.80587, 0.82034, 0.83379, 0.84658, 0.85792, 0.87354, 0.89085, 0.90904, 0.9289, 0.95157, 0.97862, 1.01337, 1.06261, 1.14631] volMatrix = [ [0.144183920277296,0.139374695503699,0.135526204819277,0.12885], [0.133703802426343,0.129893056346044,0.126909006024096,0.12175], [0.126860526863085,0.123701764371087,0.121209416342412,0.11695], [0.121720863192182,0.118881707209199,0.116979766476388,0.11381], [0.117581136690647,0.115218428824572,0.113899219047619,0.11163], [0.114363421052632,0.112523118729097,0.111637193240265,0.11019], [0.111728795180723,0.110489402985075,0.109987692307692,0.10921], [0.109805703883495,0.109100413723512,0.108870460584588,0.1086], [0.108581646586345,0.108250493273543,0.108197213114754,0.10829], [0.108190964125561,0.107986172506739,0.10796631037213,0.10822], [0.10859510460251,0.108310304612707,0.108232350773766,0.10849], [0.110043016488846,0.109404567049808,0.109102906403941,0.10919], [0.112447321958457,0.111343238289206,0.110615417475728,0.11036], [0.115567066189624,0.113888152866242,0.112830993150685,0.11201], [0.119454321849106,0.117151688909342,0.115569047072331,0.11433], [0.123858310308183,0.121275916334661,0.119199029605263,0.11731], [0.129434558979809,0.126231870274572,0.123929902439024,0.12145], [0.137335982996812,0.133099606048548,0.12994278699187,0.12723], [0.150767120085016,0.144773641066454,0.140163713821138,0.13547] ] """ # assert csv data assert len(strikes) > 0, "No valid len(strikes) found ! It is " + str(len(strikes)) assert len(expirations) > 0, "No valid len(expirations) found ! It is " + str(len(expirations)) #volMatrix = Matrix(len(strikes), len(expirations)) volMatrix = [[float(y) for y in x[1:]] for x in csv_list[1:]] # vols are for second row [1:] and for second column [1:] onward print "len(strikes) ", len(strikes) print "len(expirations) ", len(expirations) # Volatility Surface volatilitySurface = BlackVarianceSurface(Settings.instance().evaluationDate, calendar, expirations, strikes, volMatrix, dayCounter) volatilitySurface.setInterpolation("Bicubic") volatilitySurface.enableExtrapolation() volTermStructure = BlackVolTermStructureHandle(volatilitySurface) # the BS equation behind bsmProcess = BlackScholesMertonProcess(underlyingH, flatDividendTermStructure, flatTermStructure, volTermStructure) # Options discreteArithmeticAsianAverageOption = DiscreteAveragingAsianOption(averageType, runningSum, pastFixings, fixingDates, payoffAsianOption, europeanExercise) # Outputting on the screen optionTypeKeyName = dict((v,k) for k, v in vars(Option).iteritems() if v == optionType) print "Option type = ", optionTypeKeyName[optionType] print "Option maturity = ", maturity print "Underlying = ", underlying print "Strike = ", strike print "Risk-free interest rate = ", '{0:.{prec}f}%'.format(riskFreeRate*100.00, prec=4) print "Dividend yield = ", '{0:.{prec}f}%'.format(dividendYield*100.00, prec=4) print "Volatility = ", '{0:.{prec}f}%'.format(volatility*100.00, prec=4) print "Time-length between successive fixings = weekly time step" print "Previous fixings = ", pastFixings print "" # Pricing engine engine = MCDiscreteArithmeticAPEngine(bsmProcess, "LowDiscrepancy", requiredSamples=1500) discreteArithmeticAsianAverageOption.setPricingEngine(engine) # Timer start = time.time() print "Discrete ArithMC Price: ", discreteArithmeticAsianAverageOption.NPV() print ' in ' + '{0:.2f}'.format(time.time() - start), 's\n'


VolMatrixA.csv file is the data source of the Volatility Surface

VolMatrixA.csv    Select all
Strike ,6/27/2017,9/27/2017,12/27/2017,6/27/2018 0.67263,0.144183920277296,0.139374695503699,0.135526204819277,0.12885 0.71865,0.133703802426343,0.129893056346044,0.126909006024096,0.12175 0.7487,0.126860526863085,0.123701764371087,0.121209416342412,0.11695 0.77129,0.121720863192182,0.118881707209199,0.116979766476388,0.11381 0.78984,0.117581136690647,0.115218428824572,0.113899219047619,0.11163 0.80587,0.114363421052632,0.112523118729097,0.111637193240265,0.11019 0.82034,0.111728795180723,0.110489402985075,0.109987692307692,0.10921 0.83379,0.109805703883495,0.109100413723512,0.108870460584588,0.1086 0.84658,0.108581646586345,0.108250493273543,0.108197213114754,0.10829 0.85792,0.108190964125561,0.107986172506739,0.10796631037213,0.10822 0.87354,0.10859510460251,0.108310304612707,0.108232350773766,0.10849 0.89085,0.110043016488846,0.109404567049808,0.109102906403941,0.10919 0.90904,0.112447321958457,0.111343238289206,0.110615417475728,0.11036 0.9289,0.115567066189624,0.113888152866242,0.112830993150685,0.11201 0.95157,0.119454321849106,0.117151688909342,0.115569047072331,0.11433 0.97862,0.123858310308183,0.121275916334661,0.119199029605263,0.11731 1.01337,0.129434558979809,0.126231870274572,0.123929902439024,0.12145 1.06261,0.137335982996812,0.133099606048548,0.12994278699187,0.12723 1.14631,0.150767120085016,0.144773641066454,0.140163713821138,0.13547