American Option¶
An option is a financial contract that allows an investor to exercise a choice between two subcontracts. We implement in BitML the American option, where the investor can exercise the choice anytime before a given deadline.
We start by defining the parametric contract (AmericanOption Part t Contract1 Contract2 Default)
.
The parameter of the contract are: a participant Part
who can choose, before deadline t
,
to authorise the either Contract1
or Contract2
.
If time t
passes, the contract can proceed as the parameter contract Default
.
We exploit the American Option to implement an investment contract between
an investor A
and an issuer I
.
After stipulating the contract, A
can choose whether to invest, or to retract.
If she authorise the contract Invest
,
she immediately pays her 1 BTC deposit to I
, expecting to get back 1.1 BTC
from I
after block 160000000.
If she authorise the contract Retract
, she does not invest,
but she only gets back 0.95 BTC, paying 0.05 BTC to I
as a fee.
Otherwise, if she doesn’t chose before the deadline t
,
I
can invoke the contract Default
,
which returns A
’s deposit to her, minus a 0.1 BTC penalty,
which goes to I
.
Finally, we verify that the contract is liquid.
#lang bitml
(participant "A" "0339bd7fade9167e09681d68c5fc80b72166fe55bbb84211fd12bde1d57247fbe1")
(participant "I" "034a7192e922118173906555a39f28fa1e0b65657fc7f403094da4f85701a5f809")
(debug-mode)
(define (txA) ".")
(define (txFee) "..")
(define (txI) "...")
;; Part can choose at time t whether to execute Contract1 or Contract2
;; after deadline t, the contract Default can be executed
;--------------------------------------------------------------
(define (AmericanOption Part t Contract1 Contract2 Default)
(choice
(auth Part (tau (ref (Contract1))))
(auth Part (tau (ref (Contract2))))
(after t (tau (ref (Default))))))
; Sub-contracts used to instantiate the American Option
;--------------------------------------------------------------
;; A chooses not to proceed with the investment,
;; and gets back her deposit minus a cancellation fee.
;; I gets gets the fee from A.
(define (Retract)
(split
(0.95 -> (withdraw "A"))
(0.05 -> (withdraw "I"))))
;; A chooses to proceed with the investment.
;; The funds are locked up to a certain time,
;; then she can withdraw the whole balance
(define (Invest)
(split
(1 -> (withdraw "I"))
(0 -> (after 160000000 (put (x) (withdraw "A"))))))
;; A failed to choose whether to invest or retract.
;; She gets back her deposit minus a penalty.
;; I gets gets the penalty from A.
(define (Default)
(split
(0.9 -> (withdraw "A"))
(0.1 -> (withdraw "I"))))
;--------------------------------------------------------------
(contract
(pre (deposit "A" 1 (ref (txA)))
(vol-deposit "I" x 1.1 (ref (txI)))
(fee "A" 0.01 (ref (txFee))))
(ref (AmericanOption "A" 1550000 Retract Invest Default))
(check-liquid))
This is the result of the compilation.
const pubkeyA13 = pubkey:0339bd7fade9167e09681d68c5fc80b72166fe55bbb84211fd12bde1d57247fbe1
const pubkeyI2 = pubkey:034a7192e922118173906555a39f28fa1e0b65657fc7f403094da4f85701a5f809
const pubkeyA11 = pubkey:0339bd7fade9167e09681d68c5fc80b72166fe55bbb84211fd12bde1d57247fbe1
const pubkeyA1 = pubkey:0339bd7fade9167e09681d68c5fc80b72166fe55bbb84211fd12bde1d57247fbe1
const pubkeyA9 = pubkey:0339bd7fade9167e09681d68c5fc80b72166fe55bbb84211fd12bde1d57247fbe1
const pubkeyA7 = pubkey:0339bd7fade9167e09681d68c5fc80b72166fe55bbb84211fd12bde1d57247fbe1
const pubkeyI10 = pubkey:034a7192e922118173906555a39f28fa1e0b65657fc7f403094da4f85701a5f809
const pubkeyI6 = pubkey:034a7192e922118173906555a39f28fa1e0b65657fc7f403094da4f85701a5f809
const pubkeyI8 = pubkey:034a7192e922118173906555a39f28fa1e0b65657fc7f403094da4f85701a5f809
const pubkeyA3 = pubkey:0339bd7fade9167e09681d68c5fc80b72166fe55bbb84211fd12bde1d57247fbe1
const pubkeyA5 = pubkey:0339bd7fade9167e09681d68c5fc80b72166fe55bbb84211fd12bde1d57247fbe1
const pubkeyA15 = pubkey:0339bd7fade9167e09681d68c5fc80b72166fe55bbb84211fd12bde1d57247fbe1
const pubkeyI12 = pubkey:034a7192e922118173906555a39f28fa1e0b65657fc7f403094da4f85701a5f809
const pubkeyI4 = pubkey:034a7192e922118173906555a39f28fa1e0b65657fc7f403094da4f85701a5f809
const pubkeyI14 = pubkey:034a7192e922118173906555a39f28fa1e0b65657fc7f403094da4f85701a5f809
const pubkeyI16 = pubkey:034a7192e922118173906555a39f28fa1e0b65657fc7f403094da4f85701a5f809
const pubkeyA = pubkey:0339bd7fade9167e09681d68c5fc80b72166fe55bbb84211fd12bde1d57247fbe1
const pubkeyI = pubkey:034a7192e922118173906555a39f28fa1e0b65657fc7f403094da4f85701a5f809
const sigA0 : signature = _ //add signature for output .
const sigAFee : signature = _ //add signature for output ..
transaction Tinit {
input = [ .:sigA0; ..:sigAFee ]
output = 1.0097 BTC : fun(sA, sI) . (( versig(pubkeyA1, pubkeyI2; sA, sI) ||
versig(pubkeyA3, pubkeyI4; sA, sI) ||
versig(pubkeyA5, pubkeyI6; sA, sI) ))
}
const sigAT1 : signature = _
const sigIT1 : signature = _
transaction T1 {
input = [ Tinit@0: sigAT1 sigIT1 ]
output = 1.0094 BTC : fun(sA, sI) . versig(pubkeyA7, pubkeyI8; sA, sI)
}
const sigAT2 : signature = _
const sigIT2 : signature = _
transaction T2 {
input = [ T1@0: sigAT2 sigIT2 ]
output = [ 0.95455 BTC : fun(sA, sI) . ((versig(pubkeyA9, pubkeyI10; sA, sI)));
0.05455 BTC : fun(sA, sI) . ((versig(pubkeyA11, pubkeyI12; sA, sI))) ]
}
const sigAT3 : signature = _
const sigIT3 : signature = _
transaction T3 {
input = [ T2@0: sigAT3 sigIT3 ]
output = 0.95425 BTC : fun(x) . versig(pubkeyA; x)
}
const sigAT4 : signature = _
const sigIT4 : signature = _
transaction T4 {
input = [ T2@1: sigAT4 sigIT4 ]
output = 0.05425 BTC : fun(x) . versig(pubkeyI; x)
}
const sigAT5 : signature = _
const sigIT5 : signature = _
transaction T5 {
input = [ Tinit@0: sigAT5 sigIT5 ]
output = 1.0094 BTC : fun(sA, sI) . versig(pubkeyA13, pubkeyI14; sA, sI)
}
const sigAT6 : signature = _
const sigIT6 : signature = _
transaction T6 {
input = [ T5@0: sigAT6 sigIT6 ]
output = [ 1.00455 BTC : fun(sA, sI) . ((versig(pubkeyA11, pubkeyI12; sA, sI)));
0.00455 BTC : fun(sA, sI) . ((versig(pubkeyA15, pubkeyI16; sA, sI))) ]
}
const sigAT7 : signature = _
const sigIT7 : signature = _
transaction T7 {
input = [ T6@0: sigAT7 sigIT7 ]
output = 1.00425 BTC : fun(x) . versig(pubkeyI; x)
}
const sigx : signature = _ //add signature for output ...
const sigAT8 : signature = _
const sigIT8 : signature = _
transaction T8 {
input = [ T6@1: sigAT8 sigIT8 ]
output = 1.10425 BTC : fun(sA, sI) . versig(pubkeyA9, pubkeyI10; sA, sI)
}
const sigAT9 : signature = _
const sigIT9 : signature = _
transaction T9 {
input = [ T8@0: sigAT9 sigIT9 ]
output = 1.10395 BTC : fun(x) . versig(pubkeyA; x)
}
const sigAT10 : signature = _
const sigIT10 : signature = _
transaction T10 {
input = [ Tinit@0: sigAT10 sigIT10 ]
output = 1.0094 BTC : fun(sA, sI) . versig(pubkeyA11, pubkeyI12; sA, sI)
}
const sigAT11 : signature = _
const sigIT11 : signature = _
transaction T11 {
input = [ T10@0: sigAT11 sigIT11 ]
output = 1.0091 BTC : fun(x) . versig(pubkeyI; x)
}