Tuesday, October 31, 2017

Android Studio 3.0 release (Oct 2017)

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

app/build.gradle    Select all
apply plugin: 'com.android.application' apply plugin: 'kotlin-android' apply plugin: 'kotlin-android-extensions' android { compileSdkVersion 23 buildToolsVersion '26.0.2' // for Android Studio 3.0 Release 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+' // should match compileSdkVersion 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" } /* Does not need these for Android Studio 3.0 Release // add these tasks in run config to make kotlin test working in Android Studio Preview Beta // 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.1-all.zip // for Android Studio 3.0 Release



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.51' // for Android Studio 3.0 Release repositories { google() // for Android Studio 3.0 Release jcenter() } dependencies { classpath 'com.android.tools.build:gradle:3.0.0' // for Android Studio 3.0 Release 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 { google() // for Android Studio 3.0 Release jcenter() } } 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 Release

app/build.gradle    Select all
apply plugin: 'com.android.application' android { compileSdkVersion 23 buildToolsVersion '26.0.2' // for Android Studio 3.0 Release defaultConfig { applicationId 'com.beginndkgamecode.hellodroid' minSdkVersion 9 targetSdkVersion 16 versionCode 1 versionName "1.0" archivesBaseName = 'HELLODRIOD_' + versionName ndk { abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64' // arm64 added } 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+' // should match compileSdkVersion compile 'com.android.support.constraint:constraint-layout:1.0.2+' } repositories { mavenCentral() }

app/src/main/jni/Application.mk    Select all
APP_PLATFORM := android-23 APP_ABI := armeabi-v7a arm64-v8a 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 { google() // for Android Studio 3.0 Release jcenter() } dependencies { classpath 'com.android.tools.build:gradle:3.0.0' // for Android Studio 3.0 Release } } allprojects { repositories { google() // for Android Studio 3.0 Release jcenter() } }



gradle-wrapper.properties    Select all
distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists #updated to gradle-4.1-all.zip for Android Studio 3.0 Release distributionUrl=https\://services.gradle.org/distributions/gradle-4.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.


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)


Monday, April 24, 2017

How to install iOS toolchain for Windows 64 bit

The instructions are here https://coolstar.org/theos.pdf
First, to install Cygwin (Run setup-x86_64.exe) for 64 bit versions of Windows with wget, git, ca-certificates, make, perl, openssh and python packages
Suggest to install zip and unzip packages as well.

The setup scripts for theos, toolchain and sdks are
shellscript    Select all
# the toollchain requires sdk files which are large, bette to put them in external drive cd /cygdrive/e git clone https://github.com/coolstar/theos.git && mkdir -p theos/toolchain/windows git clone -b x86_64 https://github.com/coolstar/iOSToolchain4Win.git theos/toolchain/windows/iphone # setup environment variable for THEOS export THEOS=/cygdrive/e/theos # update theos submodule cd $THEOS git submodule update --init --recursive mkdir -p $THEOS/sdks cd $THEOS/sdks # install the sdk by extracting the .tbz2 files # for example tar xjvf iPhoneOS8.1.sdk.tbz2 # create a Projects Folder outside theos folder cd ~ mkdir -p Projects cd Projects # create iPhone/tool project name "hello" $THEOS/bin/nic.pl cd hello make


Additional SDKs are here
iPhoneOS9.1.sdk.tbz2 (armv7, armv7s, arm64) https://mega.nz/#!PlxzHYjA!5c02sMSF6AE1M5CjuMt66tpFWHFx6sms_zeNyGMCukQ
iPhoneOS8.1.sdk.tbz2 (armv7, armv7s, arm64) https://mega.nz/#!us40SJaa!EpVL_VUgUji_H6QuTY_0YX7IG3ljTDrpzQgA1DMh2l8
iPhoneOS7.1.sdk.tbz2 (armv7, armv7s, arm64) https://mega.nz/#!qgYgmKgA!UR3dQ9ryusm251B8QcvUIo-DS_E2WXcDZENoa3q07RE
iPhoneOS6.1.sdk.tbz2 (armv7, armv7s) https://mega.nz/#!nkZDRA4D!8hJWkgYH2d3CxNtuWctCswBaAAdx4BLVuOLjGGVvKiA
iPhoneOS5.1.sdk.tbz2 (armv6, armv7) https://mega.nz/#!f4ADHaTI!FM57l5XrZMKscOoRrcwQqvtA4tzJxi7q6oDAa5QX1n0
iPhoneOS4.2.sdk.tbz2 (armv6, armv7) https://mega.nz/#!e5xA2K7b!ccK0N-y94bmSb6ifntcStAtssvD8qK9e3uAwAgrpmEU
iPhoneOS3.2.sdk.tbz2 (armv6, armv7) https://mega.nz/#!rkoylDSD!gxpXglAgcme5Wm2JurW3GCgSzUe4Y6ePMsW627xZ8hs


Edit ~/Projects/hello/Makefile to the following to allow FAT binary for different sdks
Projects/hello/Makefile    Select all
TARGET := iphone:clang # location of theos directory export THEOS=/cygdrive/e/theos # The base SDK location is what you build your app against (i.e. library files and frameworks) THEOS_PLATFORM_SDK_ROOT_armv6 = $(THEOS)/sdks/iPhoneOS5.1.sdk THEOS_PLATFORM_SDK_ROOT_armv7 = $(THEOS)/sdks/iPhoneOS7.1.sdk THEOS_PLATFORM_SDK_ROOT_armv7s = $(THEOS)/sdks/iPhoneOS7.1.sdk THEOS_PLATFORM_SDK_ROOT_arm64 = $(THEOS)/sdks/iPhoneOS8.1.sdk SDKVERSION_armv6 = 5.1 # 5.1 (armv6, armv7) SDKVERSION_armv7 = 7.1 # 7.1 (armv7, armv7s, arm64) SDKVERSION_armv7s = 7.1 # 7.1 (armv7, armv7s, arm64) SDKVERSION_arm64 = 8.1 # 8.1 (armv7, armv7s, arm64) # The SDK for include files, usually they should match with the library files and frameworks SDK INCLUDE_SDKVERSION_armv6 = 5.1 INCLUDE_SDKVERSION_armv7 = 7.1 INCLUDE_SDKVERSION_armv7s = 7.1 INCLUDE_SDKVERSION_arm64 = 8.1 # Deployment Target is the minimum required iOS version you application needs to run # usually base sdk version >= deployment target version TARGET_IPHONEOS_DEPLOYMENT_VERSION_armv6 = 5.0 TARGET_IPHONEOS_DEPLOYMENT_VERSION_armv7 = 6.0 TARGET_IPHONEOS_DEPLOYMENT_VERSION_armv7s = 7.0 TARGET_IPHONEOS_DEPLOYMENT_VERSION_arm64 = 8.0 # the default iphone architectures for this project build IPHONE_ARCHS = armv6 armv7 armv7s arm64 # ignore warnings export GO_EASY_ON_ME=1 include $(THEOS)/makefiles/common.mk TOOL_NAME = hello hello_FILES = main.mm include $(THEOS_MAKE_PATH)/tool.mk


make again and examine the FAT binary
shellscript    Select all
cd ~/Projects/hello make clean make DEBUG=1 # examine the compiled FAT binary architecture $THEOS/toolchain/windows/iphone/bin/arm64-apple-darwin14-otool.exe -h .theos/obj/debug/hello




To install winpty in cygwin x64, type these commands
shellscript    Select all
wget --no-check-certificate https://github.com/rprichard/winpty/releases/download/0.4.2/winpty-0.4.2-cygwin-2.6.1-x64.tar.gz mkdir -p /usr/local tar xzvf winpty-0.4.2-cygwin-2.6.1-x64.tar.gz -C /usr/local/ --strip 1


Wednesday, March 29, 2017

How to install QuantLib Python for Windows 32 in offline installation

1. Download Python 2.7 Windows x86 MSI installer from

https://www.python.org/ftp/python/2.7.13/python-2.7.13.msi

2. Download required python packages and dependencies from

http://www.lfd.uci.edu/~gohlke/pythonlibs/#quantlib

QuantLib_Python‑1.9‑cp27‑cp27m‑win32.whl

Dependencies for matplotlib and others (win32)
six‑1.10.0‑py2.py3‑none‑any.whl
pyparsing‑2.2.0‑py2.py3‑none‑any.whl
packaging‑16.8‑py2.py3‑none‑any.whl
appdirs-1.4.3-py2.py3-none-any.whl
python_dateutil‑2.6.0‑py2.py3‑none‑any.whl
pytz‑2016.10‑py2.py3‑none‑any.whl
cycler‑0.10.0‑py2.py3‑none‑any.whl
setuptools‑34.3.3‑py2.py3‑none‑any.whl

numpy‑1.11.3+mkl‑cp27‑cp27m‑win32.whl
matplotlib‑1.5.3‑cp27‑cp27m‑win32.whl
xlrd-1.0.0-py2.py3-none-any.whl
pandas-0.19.2-cp27-cp27m-win32.whl
scipy‑0.19.0‑cp27‑cp27m‑win32.whl

3. Copy the above Installers and Packages to destination machine for offline installation

4. Install Python 2.7 and add Environment Variable PATH

SET PATH=C:\Python27;C:\Python27\Scripts;%PATH%

To be persistence, use sysdm.cpl to edit Advanced -> Environment Variables -> Path

or use py -2 to run python script under Windows OS without setting PATH
py -2 chap06.py

5. Install each and every the python packages above using pip

For example
pip install QuantLib_Python‑1.9‑cp27‑cp27m‑win32.whl

or if have python2 and python3 co-exist

py -2 -m pip install QuantLib_Python‑1.9‑cp27‑cp27m‑win32.whl

6. Microsoft Visual Studio not required

and no need to build your own QuantLib-Python library
However, a code editor like Microsoft VS Code is recommended.
https://code.visualstudio.com/download
(requirement : .NET Framework 4.5.2 for Windows 7)

Offline VS code extension for python can be downloaded from
https://donjayamanne.gallery.vsassets.io/_apis/public/gallery/publisher/donjayamanne/extension/python/0.6.0/assetbyname/Microsoft.VisualStudio.Services.VSIXPackage
see stack overflow discussion here http://stackoverflow.com/questions/37071388/how-to-install-vscode-extensions-offline

or NotePad ++
https://notepad-plus-plus.org/download/


7. Test

The code is borrowed from QuantLib Python Cookbook chapter 06 (requires QuantLib-Python, matplotlib)
chap06.py    Select all
#! python2 #!/usr/bin/env python # pylint: disable-msg=C0103 # Interest-rate Curves # Chapter 6 EONIA curve bootstrapping # Everything You Always Wanted to Know About Multiple Interest Rate Curve Bootstrapping but Were Afraid to Ask # In[1] import math # In[2] from QuantLib import * print ("\nOut[1]:") print ("QuantLib version", QuantLib.__version__) # In[3] # setup evaluationDate today = Date(11, December,2012) Settings.instance().evaluationDate = today # In[4] # setup DepositRateHelper for 0-2 days helpers = [ DepositRateHelper(QuoteHandle(SimpleQuote(rate/100)), Period(1,Days), fixingDays, TARGET(), Following, False, Actual360()) for rate, fixingDays in [(0.04, 0), (0.04, 1), (0.04, 2)] ] # DepositRateHelper (const Handle< Quote > &rate, # const Period &tenor, # Natural fixingDays, # const Calendar &calendar, # BusinessDayConvention convention, # bool endOfMonth, # const DayCounter &dayCounter) # DepositRateHelper (Rate rate, # const Period &tenor, # Natural fixingDays, # const Calendar &calendar, # BusinessDayConvention convention, # bool endOfMonth, # const DayCounter &dayCounter) # In[5] """ Eonia(const Handle< YieldTermStructure > &h=Handle< YieldTermStructure >()) Eonia (Euro Overnight Index Average) rate fixed by the ECB HKDHibor(const Period &tenor, const Handle< YieldTermStructure > &h=Handle< YieldTermStructure >()) """ eonia = Eonia() """ http://quant.stackexchange.com/questions/32345/quantlib-python-dual-curve-bootstrapping-example swap-rate helpers used to bootstrap the LIBOR curve can take a discount curve to use. In the old single-curve examples, a SwapRateHelper instance would be created as helper = SwapRateHelper(quoted_rate, tenor, calendar, fixedLegFrequency, fixedLegAdjustment, fixedLegDayCounter, Euribor6M()) and use the curve being bootstrapped for both forecast and discounting. To use dual-curve bootstrapping, instead, you'll have to build it as helper = SwapRateHelper(quoted_rate, tenor, calendar, fixedLegFrequency, fixedLegAdjustment, fixedLegDayCounter, Euribor6M(), QuoteHandle(), Period(0,Days), # needed as default value discountCurve) # the discountCurve argument would be a handle to the OIS curve that you bootstrapped previously SwapRateHelper (Rate rate, const Period &tenor, const Calendar &calendar, Frequency fixedFrequency, BusinessDayConvention fixedConvention, const DayCounter &fixedDayCount, const boost::shared_ptr< IborIndex > &iborIndex, const Handle< Quote < &spread=Handle< Quote >(), const Period &fwdStart=0 *Days, const Handle< YieldTermStructure > &discountingCurve=Handle< YieldTermStructure >()) In the above, the additional QuoteHandle() and Period(0,Days) arguments are, unfortunately, needed because the SWIG wrappers don't support keyword arguments for this constructor; and the discountCurve argument would be a handle to the OIS curve that you bootstrapped previously. When the swap-rate helpers are instantiated as above, they will use the LIBOR curve being bootstrapped for forecast and the OIS curve for discounting. """ # In[6] # Overnight Index Swap rate # setup OISRateHelper for 1,2,3 weeks and 1 month helpers += [ OISRateHelper(2, Period(*tenor), QuoteHandle(SimpleQuote(rate/100)), eonia) for rate, tenor in [(0.070, (1,Weeks)), (0.069, (2,Weeks)), (0.078, (3,Weeks)), (0.074, (1,Months))] ] # In[7] """ DatedOISRateHelper(const Date &startDate, const Date &endDate, const Handle< Quote > &fixedRate, const boost::shared_ptr< OvernightIndex > &overnightIndex) """ # setup DatedOISRateHelper helpers += [ DatedOISRateHelper(start_date, end_date, QuoteHandle(SimpleQuote(rate/100)), eonia) for rate, start_date, end_date in [(0.046, Date(16,January,2013), Date(13,February,2013)), (0.016, Date(13,February,2013), Date(13,March,2013)), (-0.007, Date(13,March,2013), Date(10,April,2013)), (-0.013, Date(10,April,2013), Date(8,May,2013)), (-0.014, Date(8,May,2013), Date(12,June,2013))] ] # In[8] """ Overnight Index Swap rate OISRateHelper(Natural settlementDays, const Period &tenor, const Handle< Quote > &fixedRate, const boost::shared_ptr< OvernightIndex > &overnightIndex) """ # setup OISRateHelper from 15 months to 30 years helpers += [ OISRateHelper(2, Period(*tenor), QuoteHandle(SimpleQuote(rate/100)), eonia) for rate, tenor in [(0.002, (15,Months)), (0.008, (18,Months)), (0.021, (21,Months)), (0.036, (2,Years)), (0.127, (3,Years)), (0.274, (4,Years)), (0.456, (5,Years)), (0.647, (6,Years)), (0.827, (7,Years)), (0.996, (8,Years)), (1.147, (9,Years)), (1.280, (10,Years)), (1.404, (11,Years)), (1.516, (12,Years)), (1.764, (15,Years)), (1.939, (20,Years)), (2.003, (25,Years)), (2.038, (30,Years))] ] # In[9] eonia_curve_c = PiecewiseLogCubicDiscount(0, TARGET(), helpers, Actual365Fixed()) """ # QuantLib-SWIG/SWIG/piecewiseyieldcurve.i %define export_piecewise_curve(Name, Base, Interpolator) export_piecewise_curve(PiecewiseLogCubicDiscount, Discount, MonotonicLogCubic); PiecewiseYieldCurve<Base,Interpolator>( settlementDays, # Integer settlementDays, calendar, # const Calendar& calendar, instruments, # const std::vector<boost::shared_ptr<RateHelper> >& instruments, dayCounter, # const DayCounter& dayCounter, jumps, # const std::vector<Handle<Quote> >& jumps=std::vector<Handle<Quote> >(), jumpDates, # const std::vector<Date>& jumpDates = std::vector<Date>(), accuracy, # Real accuracy = 1.0e-12, i # const Interpolator& i = Interpolator() ) """ eonia_curve_c.enableExtrapolation() # In[10] today = eonia_curve_c.referenceDate() end = today+Period(2,Years) dates = [ Date(serial) for serial in range(today.serialNumber(), end.serialNumber()+1) ] rates_c = [ eonia_curve_c.forwardRate(d, TARGET().advance(d, 1, Days), Actual360(), Simple).rate()*100 for d in dates ] # In[11] import matplotlib.pyplot as plt plt.title("Multiple Interest Rate Curve Bootstrapping") plt.plot(rates_c, '-') plt.ylabel('Rates') plt.show() # get spot rates spots = [] tenors = [] today = eonia_curve_c.referenceDate() end = today+Period(2,Years) dates = [ Date(serial) for serial in range(today.serialNumber(), end.serialNumber()+1) ] #for d in eonia_curve_c.dates(): # return boost::dynamic_pointer_cast<Name>(*self)->dates(); for d in dates: day_count = Actual360() yrs = day_count.yearFraction(today, d) compounding = Simple freq = Annual zero_rate = eonia_curve_c.zeroRate(yrs, compounding, freq) tenors.append(yrs) eq_rate = zero_rate.equivalentRate(day_count, compounding, freq, today, d).rate() spots.append(100*eq_rate) plt.title('Discount Curve') plt.plot(tenors[1::], spots[1::], linewidth=2.0) plt.xlabel('tenor (Y)') plt.ylabel('spot (%)') plt.show()





8. Test2, requires QuantLib, numpy, scipy, matplotlib

The code is borrowed from QuantLib Python Cookbook chapter 13
chap13.py    Select all
#! python2 #!/usr/bin/env python # pylint: disable-msg=C0103 # Interest-rate Models # Chapter 13 Thoughts on the Convergence of Hull-White Model Monte-Carlo Simulations # In[1] import QuantLib as ql print ("\nOut[1]:") print ("QuantLib version", ql.__version__) import matplotlib.pyplot as plt import numpy as np from scipy.integrate import simps, cumtrapz, romb # % matplotlib inline import math todays_date = ql.Date(15, 1, 2015) ql.Settings.instance().evaluationDate = todays_date # In[2] # <!-- collapse=True --> def get_path_generator(timestep, hw_process, length, low_discrepancy=False, brownian_bridge=True): """ Returns a path generator The `get_path_generator` function creates the a path generator. This function takes various inputs such as """ if low_discrepancy: usg = ql.UniformLowDiscrepancySequenceGenerator(timestep) rng = ql.GaussianLowDiscrepancySequenceGenerator(usg) seq = ql.GaussianSobolPathGenerator( hw_process, length, timestep, rng,brownian_bridge) else: usg = ql.UniformRandomSequenceGenerator(timestep, ql.UniformRandomGenerator()) rng = ql.GaussianRandomSequenceGenerator(usg) seq = ql.GaussianPathGenerator( hw_process, length, timestep, rng, brownian_bridge) return seq # In[3] # <!-- collapse=True --> def generate_paths(num_paths, timestep, seq): """ The `generate_paths` function uses the generic path generator produced by the `get_path_generator` function to return a tuple of the array of the points in the time grid and a matrix of the short rates generated." """ arr = np.zeros((num_paths, timestep+1)) for i in range(num_paths): sample_path = seq.next() path = sample_path.value() time = [path.time(j) for j in range(len(path))] value = [path[j] for j in range(len(path))] arr[i, :] = np.array(value) return np.array(time), arr # In[4] # <!-- collapse=True --> def generate_paths_zero_price(spot_curve_handle, a, sigma, timestep, length, num_paths, avg_grid_array, low_discrepancy=False, brownian_bridge=True): """ This function returns a tuple (T_array, F_array), where T_array is the array of points in the time grid, and F_array is the array of the average of zero prices observed from the simulation. The `generate_paths_zero_price` essentially is a wrapper around `generate_path_generator` and `generate_paths` taking all the required raw inputs. This function returns the average of zero prices from all the paths for different points in time. I wrote this out so that I can conveniently change all the required inputs and easily plot the results." """ hw_process = ql.HullWhiteProcess(spot_curve_handle, a, sigma) seq = get_path_generator( timestep, hw_process, length, low_discrepancy, brownian_bridge ) time, paths = generate_paths(num_paths, timestep, seq) avgs = [(time[j], (np.mean([math.exp(-simps(paths[i][0:j], time[0:j])) for i in range(num_paths)]))) for j in avg_grid_array ] return zip(*avgs) def generate_paths_discount_factors(spot_curve_handle, a, sigma, timestep, length, num_paths, avg_grid_array, low_discrepancy=False, brownian_bridge=True): """ This function returns a tuple (T_array, S_matrix), where T_array is the array of points in the time grid, and S_matrix is the matrix of the spot rates for each path in the different points in the time grid. """ hw_process = ql.HullWhiteProcess(spot_curve_handle, a, sigma) seq = get_path_generator( timestep, hw_process, length, low_discrepancy, brownian_bridge ) time, paths = generate_paths(num_paths, timestep, seq) arr = np.zeros((num_paths, len(avg_grid_array))) for i in range(num_paths): arr[i, :] = [np.exp(-simps(paths[i][0:j], time[0:j])) for j in avg_grid_array ] t_array = [time[j] for j in avg_grid_array] return t_array, arr def V(t,T, a, sigma): """ Variance of the integral of short rates, used below """ return sigma*sigma/a/a*(T-t + 2.0/a*math.exp(-a*(T-t)) - 1.0/(2.0*a)*math.exp(-2.0*a*(T-t)) - 3.0/(2.0*a) ) # In[5] # <!-- collapse=True --> # Here we vary sigma with fixed a and observe the error epsilon # define constants num_paths = 500 sigma_array = np.arange(0.01,0.1,0.03) a = 0.1 timestep = 180 length = 15 # in years forward_rate = 0.05 day_count = ql.Thirty360() avg_grid_array = np.arange(12, timestep+1, 12) # generate spot curve spot_curve = ql.FlatForward( todays_date, ql.QuoteHandle(ql.SimpleQuote(forward_rate)), day_count ) spot_curve_handle = ql.YieldTermStructureHandle(spot_curve) #initialize plots figure, axis = plt.subplots() plots = [] zero_price_theory = np.array([spot_curve.discount(j*float(length)/float(timestep)) for j in avg_grid_array]) for sigma in sigma_array: term, zero_price_empirical = generate_paths_zero_price( spot_curve_handle, a, sigma, timestep, length, num_paths, avg_grid_array ) plots += axis.plot( term, np.abs(zero_price_theory - np.array(zero_price_empirical)), lw=2, alpha=0.6, label="$\sigma=$"+str(sigma) ) # plot legend labels = [p.get_label() for p in plots] legend =axis.legend(plots,labels, loc=0)#, loc=0, bbox_to_anchor=(1.1,0.4)) axis.set_xlabel("T (years)", size=12) axis.set_ylabel("|$\epsilon(T)$|", size=12) axis.set_title("Out[5]:Discount Factor Error for $a=$%0.2f and Varying $\sigma$"%a, size=14) plt.show() # In[6] # <!-- collapse=True --> # Here we vary a with fixed sigma and observe the error epsilon # define constants num_paths = 500 sigma = 0.1 a_array = np.arange(0.1, 0.51, 0.1) timestep = 180 length = 15 # in years forward_rate = 0.05 day_count = ql.Thirty360() avg_grid_array = np.arange(12, timestep+1, 12) # generate spot curve spot_curve = ql.FlatForward( todays_date, ql.QuoteHandle(ql.SimpleQuote(forward_rate)), day_count ) spot_curve_handle = ql.YieldTermStructureHandle(spot_curve) #initialize plots figure, axis = plt.subplots() plots = [] zero_price_theory = np.array([spot_curve.discount(j*float(length)/float(timestep)) for j in avg_grid_array]) for a in a_array: term, zero_price_empirical = generate_paths_zero_price( spot_curve_handle, a, sigma, timestep, length, num_paths, avg_grid_array ) plots += axis.plot( term,np.abs(zero_price_theory - np.array(zero_price_empirical)), lw=2, alpha=0.6, label="a="+str(a) ) # plot legend labels = [p.get_label() for p in plots] legend =axis.legend(plots,labels, loc=0)#, loc=0, bbox_to_anchor=(1.1,0.4)) axis.set_xlabel("T (years)", size=12) axis.set_ylabel("|$\\epsilon(T)$|", size=12) axis.set_title("Out[6]:Discount Factor Error for $\sigma$=%0.2f and Varying $a$"%sigma, size=14) plt.show() # In[7] # <!-- collapse=True --> #define constants num_paths = 500 sigma = 0.02 a = 0.1 timestep = 180 length = 15 # in years forward_rate = 0.05 day_count = ql.Thirty360() avg_grid_array = np.arange(1, timestep+1, 12) # generate spot curve spot_curve = ql.FlatForward( todays_date, ql.QuoteHandle(ql.SimpleQuote(forward_rate)), day_count ) spot_curve_handle = ql.YieldTermStructureHandle(spot_curve) term, discount_factor_matrix = generate_paths_discount_factors( spot_curve_handle, a, sigma, timestep, length, num_paths, avg_grid_array ) vol = [np.var(discount_factor_matrix[:, i]) for i in range(len(term))] l1 = plt.plot(term, 100*np.sqrt(vol),"b", lw=2, alpha=0.6, label="Empirical") vol_theory = [100*np.sqrt(math.exp(V(0,T,a, sigma))-1.0) * spot_curve_handle.discount(T) for T in term] l2 = plt.plot(term, vol_theory,"r--", lw=2, alpha=0.6, label="Theory") plots = l1+l2 labels = [p.get_label() for p in plots] legend =plt.legend(plots,labels, loc=0) plt.xlabel("Time (Years)", size=12) plt.ylabel("$\sigma_D(0,T)$ (%)", size=12) plt.title("Out[7]:Standard Deviation of Discount Factors " "(a=%0.2f, $\sigma$=%0.2f)"%(a, sigma), size=14) plt.show()




9. Test3, requires QuantLib, numpy, panda, xlrd

The code is using QuantLib, numpy, panda and xlrd to read xls data
testreadxls.py    Select all
#! python2 #!/usr/bin/env python # pylint: disable-msg=C0103 # pylint: disable-msg=C0301 # testreadxls.py import os import pandas import numpy as np import QuantLib as ql xls_file = os.path.dirname(os.path.realpath(__file__)) + '/usd_market_data_2016-07-13.xls' #alternate way to mount google drive and read xlsx file data #import os #from google.colab import drive #drive.mount('/content/drive') #xls_file = '/content/drive/My Drive/usd_market_data_2016-07-13.xlsx' # if the file is in csv format #csv_file = '/content/drive/My Drive/usd_market_data_2016-07-13.csv' #csv = pandas.read_csv(csv_file) #print("\nCSV data\n") #print(csv) #print (csv.loc[:, 'dates']) #print (csv.iloc[0:, 1]) #discounts_csv = np.array(csv.iloc[0:,1].tolist()) #print(discounts_csv) xl = pandas.ExcelFile(xls_file) print (xl.sheet_names) #df = xl.parse("usdstd") #df = xl.parse(0) # alternate way to read first worksheet filename = xls_file sheetname = 'usdois' sheet = pandas.read_excel(filename, sheetname) # Read an Excel table into a pandas DataFrame #sheet = pandas.read_excel(filename, 0) # alternate way to read first worksheet instead of name print (sheet.columns) #tenors = np.array([Date.from_timestamp(d).t for d in sheet['dates']]) today = ql.Date(21,3,2016) act365 = ql.Actual365Fixed() dates = np.array([ql.Date(d.day, d.month, d.year) for d in sheet['dates']]) #dates = np.array([ql.Date(d.day, d.month, d.year) for d in df.iloc[0:,0]]) # use iloc to read first column, all rows print ("\nusd_market_data_2016-07-13.xls dates column") print (dates) tenors = np.array([act365.yearFraction(today,ql.Date(d.day, d.month, d.year)) for d in sheet['dates']]) print ("\nusd_market_data_2016-07-13.xls dates column convert to tenor") print (tenors) print ("\nusd_market_data_2016-07-13.xls discounts column") discounts = np.array(sheet['discounts'].tolist()) #discounts = np.array(df.iloc[0:,1].tolist()) # use iloc to read second column, all rows print (discounts)


Assume the usd_market_data_2016-07-13.xls sheet usdois (first worksheet) has the following data
https://mega.nz/#!m4Bh2TJD!KVZbvAn4D_sSR8-FYJtNASkiWvY2TWZ1LokJ-vcw-u4


10. Test3, requires QuantLib, pandas, matplotlib

The code demonstrates the download of Interest Rate xml market data from markit.com and Bootstrapping IR Curve in QuantLib
test_xml_download.py    Select all
#!python2 #!/usr/bin/env python # pylint: disable-msg=C0103 # pylint: disable-msg=C0301 # test_xml_download.py from QuantLib import * print ("\nQuantLib version", QuantLib.__version__) import urllib import zipfile import xml.etree.ElementTree as ET import pandas as pd import datetime as dt from matplotlib.dates import YearLocator, MonthLocator, DateFormatter from matplotlib.ticker import FuncFormatter import sys if sys.version_info[0] >= 3: from urllib.request import urlretrieve else: # Not Python 3 - today, it is most likely to be Python 2 # But note that this might need an update when Python 4 # might be around one day from urllib import urlretrieve def to_datetime(d): """ to_datetime """ return dt.datetime(d.year(), d.month(), d.dayOfMonth()) def format_rate(r, p=2): """ format_rate """ return '{0:.{prec}f}%'.format(r*100.00, prec=p) period_dict = {str(k)+'M': (k, Months) for k in range(1, 12, 1)} d2 = {str(k)+'Y': (k, Years) for k in range(1, 50, 1)} period_dict.update(d2) (ir_currency, ir_date) = ('USD', '20170331') url = 'https://www.markit.com/news/InterestRates_%s_%s.zip' % (ir_currency, ir_date) #filehandle, _ = urllib.urlretrieve(url) filehandle, _ = urlretrieve(url) zip_file_object = zipfile.ZipFile(filehandle, 'r') interest_rate_file = zip_file_object.open(zip_file_object.namelist()[1]) content = interest_rate_file.read() #print (content) root = ET.fromstring(content) print ("\nInfo on InterestRates_%s_%s" % (ir_currency, ir_date)) for a in [root.find(b) for b in ['./currency', './effectiveasof', './deposits/daycountconvention', './deposits/snaptime', './deposits/spotdate', './swaps/fixeddaycountconvention', './swaps/floatingdaycountconvention', './swaps/snaptime', './swaps/spotdate']]: print (a.tag, a.text) effectiveasof = root.find('./effectiveasof').text currency = root.find('./currency').text today = DateParser.parseFormatted(effectiveasof, '%Y-%m-%d') Settings.instance().evaluationDate = today print ("\nDeposit Rates") deposits_maturitydates = [a.text for a in root.findall('.//deposits/curvepoint/maturitydate')] deposits_parrates_text = [a.text for a in root.findall('.//deposits/curvepoint/parrate')] deposits_tenors = [a.text for a in root.findall('.//deposits/curvepoint/tenor')] deposits_periods = [period_dict[a] for a in deposits_tenors] print (pd.DataFrame(zip(deposits_tenors, deposits_maturitydates, map(float, deposits_parrates_text)), columns=('Tenor', 'Maturity', 'Parrate'))) maturity_dict = {} for t, m in zip(deposits_tenors, deposits_maturitydates): d = {t: m} maturity_dict.update(d) print ("\nSwap Rates") swaps_maturitydates = [a.text for a in root.findall('.//swaps/curvepoint/maturitydate')] swaps_parrates_text = [a.text for a in root.findall('.//swaps/curvepoint/parrate')] swaps_tenors = [a.text for a in root.findall('.//swaps/curvepoint/tenor')] swaps_periods = [period_dict[a] for a in swaps_tenors] print (pd.DataFrame(zip(swaps_tenors, swaps_maturitydates, map(float, swaps_parrates_text)), columns=('Tenor', 'Maturity', 'Parrate'))) for t, m in zip(swaps_tenors, swaps_maturitydates): d = {t: m} maturity_dict.update(d) #print (maturity_dict) euribor6m = Euribor6M() helpers = [DepositRateHelper(rate, Period(*tenor), 2, TARGET(), Following, False, Actual360()) for tenor, rate in zip(deposits_periods, map(float, deposits_parrates_text))] helpers += [SwapRateHelper(rate, Period(*tenor), TARGET(), Semiannual, Unadjusted, Thirty360(), euribor6m) for tenor, rate in zip(swaps_periods, map(float, swaps_parrates_text))] curve = PiecewiseLogCubicDiscount(2, TARGET(), helpers, Actual360()) curve.enableExtrapolation() spot = curve.referenceDate() #dates = [spot+Period(i,Months) for i in range(0, 30*12+1)] dates = [spot+Period(i, Years) for i in range(0, 30)] rates = [curve.forwardRate(d, euribor6m.maturityDate(d), Actual360(), Simple).rate() for d in dates] valid_dates = [d for d in dates if d >= spot] import matplotlib.pyplot as plt fig, ax = plt.subplots() fig.autofmt_xdate() ax.plot_date([to_datetime(d) for d in valid_dates], rates, '-') ax.set_xlim(to_datetime(min(dates)), to_datetime(max(dates))) ax.xaxis.set_major_locator(YearLocator(2, month=today.month(), day=today.dayOfMonth())) ax.xaxis.set_major_formatter(DateFormatter("%Y")) ax.xaxis.grid(True, 'major') ax.xaxis.grid(False, 'minor') ax.yaxis.set_major_formatter(FuncFormatter(lambda r, pos: format_rate(r))) plt.title("%s Interest Rate Curve Bootstrapping, effective %s" % (currency, effectiveasof)) plt.xlabel('Year') plt.ylabel('Rates') plt.show()






11. Compile QuantLib Python 1.10 for Mac

script.sh    Select all
# install Xcode and HomeBrew # ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" # install boost brew install boost # Download QuantLib-1.10 cd $(HOME)/Downloads wget --no-check-certificate https://jaist.dl.sourceforge.net/project/quantlib/test/QuantLib-1.10.tar.gz tar xzvf QuantLib-1.10.tar.gz # Compile QuantLib 1.10 cd QuantLib-1.10 ./configure --prefix=/usr/local/ CXXFLAGS='-O2 -stdlib=libstdc++ -mmacosx-version-min=10.6' LDFLAGS='-stdlib=libstdc++ -mmacosx-version-min=10.6' make && sudo make install # test compile c++ g++ Bonds.cpp -std=c++11 -stdlib=libstdc++ -o Bonds -lQuantLib ./Bonds # Download QuantLib-SWIG 1.10 cd $(HOME)/Downloads wget --no-check-certificate https://jaist.dl.sourceforge.net/project/quantlib/test/QuantLib-SWIG-1.10.tar.gz tar xzvf QuantLib-SWIG-1.10.tar.gz # Compile QuantLib Python cd QuantLib-SWIG-1.10 ./configure CXXFLAGS='-O2 -stdlib=libstdc++ -mmacosx-version-min=10.6' make -C Python make -C Python check sudo make -C Python install # Package wheel file sudo -H python pip install setuptools wheel cd $(HOME)/Downloads/QuantLib-SWIG-1.10/Python # Modify setup.py and replace from distutils.core import setup, Extension # By try: from setuptools import setup, Extension except: from distutils.core import setup, Extension # python 2 wheel file python setup.py bdist_wheel ls dist/ # python 3 wheel file LDFLAGS="-arch x86_64 -bundle -flat_namespace -undefined suppress" CFLAGS="-fno-strict-aliasing -Wsign-compare -fno-common -static -arch x86_64 -Wno-shorten-64-to-32" python3 setup.py bdist_wheel ls dist/


QuantLib_Python-1.10-cp27-cp27m-macosx_10_10_intel.whl download

QuantLib_Python-1.10-cp36-cp36m-macosx_10_6_intel.whl download
For Python3, have to install libQuantLib to /usr/local/lib
cd /usr/local/lib
sudo tar xzvf ~/Download/libQuantLib.tgz
Download libQuantLib.tgz here https://mega.nz/#!rpJg0B6T!NlG3Ijgo0weNOi_CVOkCzpGCMRqHZkWSeF3S0sAR12o



12. For Windows 64-bit, Regeneration of python SWIG interface method
If you need to edit the SWIG interface file and add functionality in QuantLib Python, you need to regenerate.


script.cmd    Select all
# First, compile QuantLib using Visual Studio 2015. # Select 21 projects and right click select Property -> All Configurations Add C:\local\boost_1_59_0; to the Property Pages : VC++ Include directories to win32 platform and Add C:\local\boost_1_59_0\lib32-msvc-14.0; to the VC++ Libs directories to win32 platform # Select All Configurations Add C:\local\boost_1_59_0_64; to the Property Pages : VC++ Include directories to x64 platform and Add C:\local\boost_1_59_0_64\lib64-msvc-14.0; to the VC++ Libs directories to x64 platform # Add /wd4819 to Command Line : Additional Options to disable C4819 warnings when compiling Quantlib to both win32 and x64 platform # Build Release x64 Solution or Release win32 Solution. # setting of QuantLib Project directory, e.g. SET QL_DIR=C:\local\QuantLib-1.10\QuantLib-1.10 # or alternatively, edit the setup.py # QL_INSTALL_DIR = r'C:\local\QuantLib-1.10\QuantLib-1.10' # setting of compiled libraries location for QuantLib ('QuantLib-vc140-x64-mt.lib') and Boost, e.g. for x64 platform SET LIB=C:\local\boost_1_59_0_64\lib64-msvc-14.0 # setting of Boost Project directory, e.g. SET INCLUDE=C:\local\boost_1_59_0_64 # setting of SWIGWIN.exe PATH, e.g. SET PATH=C:\local\swigwin-3.0.12;%PATH% # setting of VISUAL STUDIO 2015 (Version 14) SET VS90COMNTOOLS=%VS140COMNTOOLS% # Edit SWIG interface file if any C:\local\QuantLib-1.10\QuantLib-SWIG-1.10\SWIG\*.i # e.g. edit piecewiseyieldcurve.i and add at the end # export_piecewise_curve(PiecewiseLogLinearDiscount,Discount,LogLinear); # Wrap the edited interface file again after edit py -2 setup.py wrap # compile using msvc # need to edit setup.py to add ,'/wd4819' to the extra_compile_args to disable warnings py -2 setup.py build --compiler=msvc # must use Administrator Command Prompt to install py -2 -m setup.py install --skip-build # generation of wheel file is same as above that is modify setup.py first # need to install setuptools and wheel py -2 -m pip install setuptools wheel py -2 setup.py test py -2 setup.py bdist_wheel dir dist


Visual Studio 2015 setup https://mega.nz/#!70ZwyARa!z4et3sKwguU16tEbCYTdwBC1VEkNJTTakryrDRBSKM8