1

I've built a very simple function to estimate the probability for a Long Straddle (derivative strategy) to be positive at expiration.

derivativeStrategyLongStraddle[currentPrice_, strikePrice_?NumberQ, 
    callPremium_?NumberQ, putPremium_?NumberQ] := 
    Max[0, currentPrice - strikePrice] - callPremium + 
    Max[0, strikePrice - currentPrice] - putPremium;

r= NProbability[derivativeStrategyLongStraddle[x, 39, 2.38, 0.02] >= 0, 
x \[Distributed] NormalDistribution[41.57339177753672`, 0.9105010291072763`]]

0.575516

Now, I want to accelerate this by compiling my simple derivativeStrategyLongStraddle function.

derivativeStrategyLongStraddleCompiled = 
 Compile[{{currentPrice}, {strikePrice}, {callPremium}, {putPremium}},
   Max[0, currentPrice - strikePrice] - callPremium + 
   Max[0, strikePrice - currentPrice] - putPremium, 
  RuntimeAttributes -> {Listable}]

But I get the following error message when I try to run:

rC= NProbability[derivativeStrategyLongStraddleCompiled[x, 39, 2.38, 0.02] >= 0, 
    x \[Distributed] NormalDistribution[41.57339177753672`, 0.9105010291072763`]]

CompiledFunction::cfsa: Argument x at position 1 should be a machine-size real number. >>

0.575516

Any idea why? It's the first time I use Compile so I might be missing obvious!

Xavier

Update. I've tried using N but get the same error message. How do I fix that?

rC= NProbability[derivativeStrategyLongStraddleCompiled[N[x], 39, 2.38, 0.02] >= 0, 
    x \[Distributed] NormalDistribution[41.57339177753672`, 0.9105010291072763`]]
Karsten7
  • 27,448
  • 5
  • 73
  • 134
Xavier
  • 155
  • 9

1 Answers1

3

If you use an intermediate function as demonstrated in this answer, you'll get rid of all error messages that are related to the symbolic evaluation:

derivativeStrategyLongStraddleCompiled2[currentPrice_?NumberQ, 
 strikePrice_?NumberQ, callPremium_?NumberQ, putPremium_?NumberQ] := 
  derivativeStrategyLongStraddleCompiled[currentPrice, strikePrice, callPremium, putPremium]

Unfortunately, you'll get new error messages when you evaluate

NProbability[derivativeStrategyLongStraddleCompiled2[x, 39, 2.38, 0.02] >= 0, 
 x \[Distributed] NormalDistribution[41.57339177753672, 0.9105010291072763]]
NIntegrate::slwcon: Numerical integration converging too slowly; suspect one of the following: singularity, value of the integration is 0, highly oscillatory integrand, or WorkingPrecision too small. >>
NIntegrate::ncvb: NIntegrate failed to converge to prescribed accuracy after 9 recursive bisections in x near {x} = {41.1848}. NIntegrate obtained 0.5773068754042155` and 0.040915146726462764` for the integral and error estimates. >>

0.577307

You can get rid of the last one by increasing MaxRecursion

NProbability[derivativeStrategyLongStraddleCompiled2[x, 39, 2.38, 0.02] >= 0, 
 x \[Distributed] NormalDistribution[41.57339177753672, 0.9105010291072763], 
 Method -> {"NIntegrate", MaxRecursion -> 30}]
NIntegrate::slwcon: Numerical integration converging too slowly; suspect one of the following: singularity, value of the integration is 0, highly oscillatory integrand, or WorkingPrecision too small. >>

0.575516

As this gives you the correct result, you might just switch the error message off using

Off[NIntegrate::slwcon]

By changing the Method to "MonteCarlo" you get rid of all error messages:

NProbability[derivativeStrategyLongStraddleCompiled2[x, 39, 2.38, 0.02] >= 0, 
 x \[Distributed] NormalDistribution[41.57339177753672, 0.9105010291072763], 
 Method -> "MonteCarlo"]
0.575254

However, the result might vary for each evaluation.

When using the Monte Carlo method, the intermediate function isn't needed anymore and one can use

derivativeStrategyLongStraddleCompiled3 = 
 Compile[{{currentPrice}, {strikePrice}, {callPremium}, {putPremium}},
  Max[0, currentPrice - strikePrice] - callPremium + 
  Max[0, strikePrice - currentPrice] - putPremium, 
  RuntimeAttributes -> {Listable}, RuntimeOptions -> {"EvaluateSymbolically" -> False}]

NProbability[derivativeStrategyLongStraddleCompiled3[x, 39, 2.38, 0.02] >= 0, 
 x \[Distributed] NormalDistribution[41.57339177753672, 0.9105010291072763], 
 Method -> "MonteCarlo"]
0.575254

Update:

If you exclude the points where derivativeStrategyLongStraddleCompiled2 == 0 everything works smooth:

NProbability[derivativeStrategyLongStraddleCompiled2[x, 39, 2.38, 0.02] >= 0, 
 x \[Distributed] NormalDistribution[41.57339177753672, 0.9105010291072763], 
 Method -> {"NIntegrate", Exclusions -> {39 + 2.38 + 0.02, 39 - 2.38 - 0.02}}]
0.575516
Karsten7
  • 27,448
  • 5
  • 73
  • 134