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 Canary 1

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 Canary 1 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 Canary 1 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 Canary 1

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 Canary 1 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


QuantLib Python source code, Gaussian1dModels.py (Gaussian1dModels.cpp in QuantLib Examples Folder)

Gaussian1dModels.py    Select all
#!python2 #!/usr/bin/env python #Gaussian1dModels.py import QuantLib as ql def printBasket(basket): print ("%-20s %-20s %-20s %-20s %-20s %-20s" % ("Expiry", "Maturity", "Nominal", "Rate", "MarketVol", "Pay/Rec")) print ("==================================================================================================================") for i in range(0, len(basket)): expiryDate = basket[i].swaptionExpiryDate() endDate = basket[i].swaptionMaturityDate() nominal = basket[i].swaptionNominal() vol = basket[i].volatility().value() rate = basket[i].swaptionStrike() #type = basket[i].swaption.type() print ("%-20s %-20s %-20f %-20f %-20f" % (str(expiryDate), str(endDate), nominal, rate, vol)) print("==================================================================================================================") def printModelCalibration(basket, volatility): print ("%-20s %-20s %-20s %-20s %-20s %-20s" % ("Expiry","Model sigma","ModelPrice","MarketPrice","Model impVol","Market impVol")) print ("=================================================================================================================") for i in range(0, len(basket)): expiryDate = basket[i].swaptionExpiryDate() modelValue = basket[i].modelValue() marketValue= basket[i].marketValue() impVol = basket[i].impliedVolatility(modelValue, 1e-6, 1000, 0.0, 2.0) vol = basket[i].volatility().value() print ("%-20s %-20f %-20f %-20f %-20f %-20f" % (str(expiryDate), volatility[i], modelValue, marketValue, impVol, vol)) print("==================================================================================================================") refDate = ql.Date(30, 4, 2014) # Date refDate(30, April, 2014); ql.Settings.instance().setEvaluationDate(refDate) # Settings::instance().evaluationDate() = refDate; forward6mQuote = ql.QuoteHandle(ql.SimpleQuote(0.025)) # Handle<Quote> forward6mQuote(boost::make_shared(0.025)); oisQuote = ql.QuoteHandle(ql.SimpleQuote(0.02)) # Handle<Quote> oisQuote(boost::make_shared(0.02)); volQuote = ql.QuoteHandle(ql.SimpleQuote(0.2)) # Handle<Quote> volQuote(boost::make_shared(0.2)); dc = ql.Actual365Fixed() yts6m = ql.FlatForward(refDate, forward6mQuote, dc) ytsOis= ql.FlatForward(refDate, oisQuote, dc) yts6m.enableExtrapolation() ytsOis.enableExtrapolation() hyts6m = ql.RelinkableYieldTermStructureHandle(yts6m) t0_curve = ql.YieldTermStructureHandle(yts6m) t0_Ois = ql.YieldTermStructureHandle(ytsOis) euribor6m = ql.Euribor6M(hyts6m) swaptionVol = ql.ConstantSwaptionVolatility(0, ql.TARGET(), ql.ModifiedFollowing, volQuote, ql.Actual365Fixed()) # Handle<SwaptionVolatilityStructure> swaptionVol(boost::make_shared(0, TARGET(), ModifiedFollowing, volQuote, Actual365Fixed())); effectiveDate = ql.TARGET().advance(refDate, ql.Period('2D')) # Date effectiveDate = TARGET().advance(refDate, 2 * Days); maturityDate = ql.TARGET().advance(effectiveDate, ql.Period('10Y')) # Date maturityDate = TARGET().advance(effectiveDate, 10 * Years); fixedSchedule = ql.Schedule(effectiveDate, maturityDate, ql.Period('1Y'), ql.TARGET(), ql.ModifiedFollowing, ql.ModifiedFollowing, ql.DateGeneration.Forward, False) # Schedule fixedSchedule(effectiveDate, maturityDate, 1 * Years, TARGET(), ModifiedFollowing, ModifiedFollowing, DateGeneration::Forward, false); floatSchedule = ql.Schedule(effectiveDate, maturityDate, ql.Period('6M'), ql.TARGET(), ql.ModifiedFollowing, ql.ModifiedFollowing, ql.DateGeneration.Forward, False) # Schedule floatingSchedule(effectiveDate, maturityDate, 6 * Months, TARGET(), ModifiedFollowing, ModifiedFollowing, DateGeneration::Forward, false); # Vector input for the NonstandardSwap obj fixedNominal = [1 for x in range(0,len(fixedSchedule)-1)] floatingNominal = [1 for x in range(0,len(floatSchedule)-1)] strike = [0.04 for x in range(0,len(fixedSchedule)-1)] spread = [0 for x in range(0,len(floatSchedule)-1)] gearing = [1 for x in range(0,len(floatSchedule)-1)] underlying = ql.NonstandardSwap(ql.VanillaSwap.Payer, fixedNominal, floatingNominal, fixedSchedule, strike, ql.Thirty360(), floatSchedule, euribor6m, gearing, spread, ql.Actual360(), False, False, ql.ModifiedFollowing) # boost::shared_ptr<NonstandardSwap> underlying = boost::make_shared<NonstandardSwap>(VanillaSwap(VanillaSwap::Payer, 1.0, fixedSchedule, strike, Thirty360(), floatingSchedule, euribor6m, 0.00, Actual360())); exerciseDates = [ql.TARGET().advance(x, -ql.Period('2D')) for x in fixedSchedule] exerciseDates = exerciseDates[1:-1] # std::vector<Date> exerciseDates; # for (Size i = 1; i < 10; ++i) # exerciseDates.push_back(TARGET().advance(fixedSchedule[i], -2 * Days)); exercise = ql.BermudanExercise(exerciseDates) # boost::shared_ptr<Exercise> exercise = boost::make_shared<BermudanExercise>(exerciseDates, false); swaption = ql.NonstandardSwaption(underlying,exercise,ql.Settlement.Physical) # boost::shared_ptr<NonstandardSwaption> swaption = boost::make_shared<NonstandardSwaption>(underlying, exercise); stepDates = exerciseDates[:-1] # std::vector<Date> stepDates(exerciseDates.begin(), exerciseDates.end() - 1); sigmas = [ql.QuoteHandle(ql.SimpleQuote(0.01)) for x in range(1, 10)] # std::vector<Real> sigmas(stepDates.size() + 1, 0.01); reversion = [ql.QuoteHandle(ql.SimpleQuote(0.01))] # Real reversion = 0.01; gsr = ql.Gsr(t0_curve, stepDates, sigmas, reversion) # boost::shared_ptr<Gsr> gsr = boost::make_shared<Gsr>(yts6m, stepDates, sigmas, reversion); swaptionEngine = ql.Gaussian1dSwaptionEngine(gsr, 64, 7.0, True, False, t0_Ois) # boost::shared_ptr<PricingEngine> swaptionEngine = boost::make_shared<Gaussian1dSwaptionEngine>(gsr, 64, 7.0, true, false, ytsOis); nonstandardSwaptionEngine = ql.Gaussian1dNonstandardSwaptionEngine(gsr, 64, 7.0, True, False, ql.QuoteHandle(ql.SimpleQuote(0)), t0_Ois) # boost::shared_ptr<PricingEngine> nonstandardSwaptionEngine = boost::make_shared<Gaussian1dNonstandardSwaptionEngine>(gsr, 64, 7.0, true, false, Handle<Quote>(), ytsOis); swaption.setPricingEngine(nonstandardSwaptionEngine) # swaption->setPricingEngine(nonstandardSwaptionEngine); swapBase = ql.EuriborSwapIsdaFixA(ql.Period('10Y'), t0_curve, t0_Ois) # boost::shared_ptr<SwapIndex> swapBase = boost::make_shared<EuriborSwapIsdaFixA>(10 * Years, yts6m, ytsOis); basket = swaption.calibrationBasket(swapBase, swaptionVol, 'Naive') # std::vector<boost::shared_ptr<CalibrationHelper> > basket = swaption->calibrationBasket(swapBase, *swaptionVol, BasketGeneratingEngine::Naive); for i in range(0, len(basket)): basket[i].setPricingEngine(swaptionEngine) # for (Size i = 0; i < basket.size(); ++i) basket[i]->setPricingEngine(swaptionEngine); method = ql.LevenbergMarquardt() # LevenbergMarquardt method; ec = ql.EndCriteria(1000, 10, 1e-8, 1e-8, 1e-8) # EndCriteria ec(1000, 10, 1E-8, 1E-8, 1E-8); gsr.calibrateVolatilitiesIterative(basket, method, ec) # gsr->calibrateVolatilitiesIterative(basket, method, ec); printBasket(basket) printModelCalibration(basket, gsr.volatility()) npv = swaption.NPV() print(npv)