Closed mrt181 closed 8 years ago
I assume the reason is that the valuation for a put can be done via the call using put-call-parity: valuePut = valueCall - (forward-strike)*payoffUnit
I consider adding a flag to value a put, if it is convenient.
ok, using that formula and these inputs I get a value which looks wrong.
I have some error but where?
double marketprice = 12.35d;
Double interestRate = 0.02d;
Double volatility = 0.02d;
double runtime = 7.466681599999999d; // hours
double strikeprice = 12.5d;
protected double getOptionValue(double marketprice, Double interestRate, Double volatility, double runtime, double strikeprice) {
double forward = strikeprice * Math.exp(interestRate * runtime); // 14.513253643305523
double payoff = Math.exp(-interestRate * runtime); // 0.8612817158174474
double callValue = blackScholesOptionValue(marketprice, interestRate, volatility, runtime, strikeprice); // 1.585196389882374
double putValue = callValue - forward * payoff; // -10.914803610117627
return putValue;
}
I just had a quick look.
First, the formula is
double putValue = callValue - (forward-strikeprice) * payoff;
but your implementation is
double putValue = callValue - forward * payoff;
Second, I believe there is an error in the calculation of the forward. The forward is
double forward = marketprice * Math.exp(interestRate * runtime);
but your implementation is
double forward = strikeprice * Math.exp(interestRate * runtime);
Also, the comment after runtime
(maturity) is "hours", but note that interest rates and volatility are often annualized, in which case runtime is a year fraction (years). Of course, if you have another definition of interest rates and volatility, then the definition of time may be different (but 2% per hour looks like a high rate). I assume 7.4667 are approximately 7 and a half year.
OK, i miss read (forward-strike) as a variable instead of an operation and fixed the error. I got the hour part from the project owner.
I have changed the method - I have two implementations, one for put and one for call values
/**
* @return the put option value
*/
@Override
protected double getOptionValue(double marketprice, double interestRate, double volatility, double runtime, double strikeprice) {
double callMarketprice = strikeprice;
double forward = marketprice * Math.exp(interestRate * runtime);
double callStrikeprice = marketprice;
double payoff = Math.exp(-interestRate * runtime);
double callValue = blackScholesOptionValue(callMarketprice, interestRate, volatility, runtime, callStrikeprice);
double putValue = callValue - (forward - strikeprice) * payoff;
LOGGER.info("bid price (marketprice): {}", marketprice);
LOGGER.info("ask price : {}", callMarketprice);
LOGGER.info("forward = {} * {}", marketprice, Math.exp(interestRate * runtime));
LOGGER.info("forward : {}", forward);
LOGGER.info("strike : {}", strikeprice);
LOGGER.info("payoff = Math.exp({} * {})", -interestRate, runtime);
LOGGER.info("payoff : {}", payoff);
LOGGER.info("callValue = blackScholesOptionValue({}, {}, {}, {}, {})", callMarketprice, interestRate, volatility, runtime, callStrikeprice);
LOGGER.info("callValue : {}", callValue);
LOGGER.info("putValue = {} - ({} - {}) * {}", callValue, forward, strikeprice, payoff);
LOGGER.info("putValue : {}", putValue);
return putValue;
}
/**
* @return the call option value
*/
@Override
protected double getOptionValue(double marketprice, double interestRate, double volatility, double runtime, double strikeprice) {
double callValue = blackScholesOptionValue(marketprice, interestRate, volatility, runtime, strikeprice);
LOGGER.info("ask price (marketprice): {}", marketprice);
LOGGER.info("bid price : {}", strikeprice);
LOGGER.info("strike : {}", strikeprice);
LOGGER.info("callValue = blackScholesOptionValue({}, {}, {}, {}, {})", marketprice, interestRate, volatility, runtime, strikeprice);
LOGGER.info("callValue : {}", callValue);
return callValue;
}
This yields these results.
// putValue
bid price (marketprice): 9.0
ask price : 13.775
forward = 9.0 * 1.4115203078039358
forward : 12.703682770235423
strike : 13.775
payoff = Math.exp(-0.02 * 17.2333678)
payoff : 0.7084559779064141
callValue = blackScholesOptionValue(13.775, 0.02, 0.02, 17.2333678, 9.0)
callValue : 7.398896198842273
putValue = 7.398896198842273 - (12.703682770235423 - 13.775) * 0.7084559779064141
putValue : 8.157877294503127
// callValue
ask price (marketprice): 13.775
bid price : 9.0
strike : 9.0
callValue = blackScholesOptionValue(13.775, 0.02, 0.02, 17.2333678, 9.0)
callValue : 7.398896198842273
I hope I am doing it correctly now.
It is unclear to me why you swap "spot" and "strike" (you call it marketprice and strikeprice) for the call. Maybe I miss s.th. here. The best way to get confidence on your result is
I was simply doing it all wrong but i got it now. I get the maturity in minutes but convert it to years before passing it to this method.
/**
* @return the put option value
*/
@Overrid
protected double getOptionValue(double spot, double rate, double volatility, double maturity, double strike) {
double payoff = Math.exp(-rate * maturity);
double callValue = blackScholesOptionValue(spot, rate, volatility, maturity, strike);
double putValue = strike * payoff - spot + callValue;
return putValue;
}
This looks better. I have added a method which features a flag "isCall" https://github.com/finmath/finmath-lib/blob/master/src/main/java/net/finmath/functions/AnalyticFormulas.java#L139
In
net.finmath.functions.AnalyticFormulas
I can find functions to calculate different option values for call options using black-scholes.But there is no function to calculate the option value of a put option? Am I missing something?