1
$\begingroup$

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`]]
$\endgroup$
  • $\begingroup$ See http://mathematica.stackexchange.com/a/55484/18476 on how to prohibit symbolic evaluation for your compiled function. $\endgroup$ – Karsten 7. Oct 19 '14 at 10:37
  • $\begingroup$ Thanks. I'll try and let you know if it fixed the problem. $\endgroup$ – Xavier Oct 19 '14 at 10:49
  • $\begingroup$ I've tried "RuntimeOptions -> {"EvaluateSymbolically" -> False}and it adds more error messages, so really doesn't fix my problem. I've tried "RuntimeOptions -> {"WarningMessages"->False} and removes the error message but doesn't fix the problem. Any other ideas? $\endgroup$ – Xavier Oct 19 '14 at 13:56
3
$\begingroup$

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
$\endgroup$
  • $\begingroup$ @Xavier see my update for a real solution, instead of the workarounds. $\endgroup$ – Karsten 7. Oct 20 '14 at 7:13
  • $\begingroup$ I like that!! Thanks! $\endgroup$ – Xavier Oct 21 '14 at 8:06

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.