Assembla home | Assembla project page
 

Changeset 165

Show
Ignore:
Timestamp:
05/13/08 21:39:43 (5 months ago)
Author:
snovik
Message:

New: Testing of FD for American Option is completed

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/QLNet/EquityOption/EquityOption.cs

    r162 r165  
    133133            method = "Finite differences"; 
    134134            europeanOption.setPricingEngine(new FDEuropeanEngine(bsmProcess,timeSteps,timeSteps-1)); 
    135             //bermudanOption.setPricingEngine(boost::shared_ptr<PricingEngine>( 
    136             //             new FDBermudanEngine(bsmProcess,timeSteps,timeSteps-1))); 
     135            //bermudanOption.setPricingEngine(new FDBermudanEngine(bsmProcess,timeSteps,timeSteps-1))); 
    137136            americanOption.setPricingEngine(new FDAmericanEngine(bsmProcess,timeSteps,timeSteps-1)); 
    138137 
    139138            Console.Write("{0,-" + widths[0] + "}", method); 
    140139            Console.Write("{0,-" + widths[1] + ":0.000000}", europeanOption.NPV()); 
    141             //Console.Write("{0,-" + widths[2] + ":0.000000}", bermudanOption.NPV()); 
     140            Console.Write("{0,-" + widths[2] + ":0.000000}", bermudanOption.NPV()); 
    142141            Console.WriteLine("{0,-" + widths[3] + ":0.000000}", americanOption.NPV()); 
    143142 
  • trunk/QLNet/QLNet.vsmdi

    r143 r165  
    55      <TestLink id="bbe2d937-bb70-a666-a879-b3063800a42e" name="testFairSpread" storage="test2008\bin\debug\test2008.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel,   PublicKeyToken=b03f5f7f11d50a3a" /> 
    66      <TestLink id="25b4118b-8066-f12f-3687-a5ef1886eb1c" name="testInArrears" storage="test2008\bin\debug\test2008.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel,   PublicKeyToken=b03f5f7f11d50a3a" /> 
     7      <TestLink id="27ded393-6046-4057-bd65-31f629c9bf55" name="testFairRate" storage="test2008\bin\debug\test2008.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel,   PublicKeyToken=b03f5f7f11d50a3a" /> 
    78      <TestLink id="0ee842b0-6275-252f-a1d0-000b0a6a4c52" name="testCachedValue" storage="test2008\bin\debug\test2008.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel,   PublicKeyToken=b03f5f7f11d50a3a" /> 
    8       <TestLink id="27ded393-6046-4057-bd65-31f629c9bf55" name="testFairRate" storage="test2008\bin\debug\test2008.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel,   PublicKeyToken=b03f5f7f11d50a3a" /> 
    99      <TestLink id="3b1816a9-7785-f64f-bc52-7014af11e8e5" name="testSpreadDependency" storage="test2008\bin\debug\test2008.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel,   PublicKeyToken=b03f5f7f11d50a3a" /> 
    1010      <TestLink id="2b04fe68-610a-b2de-e241-ef9a50fdb3fb" name="testRateDependency" storage="test2008\bin\debug\test2008.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel,   PublicKeyToken=b03f5f7f11d50a3a" /> 
     
    4747    </TestLinks> 
    4848  </TestList> 
     49  <TestList name="American Option" id="da9a808d-acf7-4baf-9dfb-e4b091d30fef" parentListId="8c43106b-9dc1-4907-a29f-aa66a61bf5b6"> 
     50    <TestLinks> 
     51      <TestLink id="33c4d801-48ac-44c4-329e-d6fe84f5e034" name="testJuValues" storage="test2008\bin\debug\test2008.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel,   PublicKeyToken=b03f5f7f11d50a3a" /> 
     52      <TestLink id="3be50179-04ee-902d-73d8-3c94e9305a67" name="testFdShoutGreeks" storage="test2008\bin\debug\test2008.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel,   PublicKeyToken=b03f5f7f11d50a3a" /> 
     53      <TestLink id="783f96db-cce8-bf61-b280-f5010f7d7eb3" name="testFdValues" storage="test2008\bin\debug\test2008.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel,   PublicKeyToken=b03f5f7f11d50a3a" /> 
     54      <TestLink id="1e42c90a-8e82-1369-9ed9-52b036b1c07e" name="testBjerksundStenslandValues" storage="test2008\bin\debug\test2008.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel,   PublicKeyToken=b03f5f7f11d50a3a" /> 
     55      <TestLink id="9f4ff6f8-9938-8ecb-5608-7dbc928cbda3" name="testFdAmericanGreeks" storage="test2008\bin\debug\test2008.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel,   PublicKeyToken=b03f5f7f11d50a3a" /> 
     56      <TestLink id="2bbf531b-68cb-84c0-a06f-6bedfb89f20f" name="testBaroneAdesiWhaleyValues" storage="test2008\bin\debug\test2008.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel,   PublicKeyToken=b03f5f7f11d50a3a" /> 
     57    </TestLinks> 
     58  </TestList> 
    4959  <TestList name="PiecewiseYieldCurve" id="db6f77ff-70a4-4779-821e-8f5548c91d54" parentListId="8c43106b-9dc1-4907-a29f-aa66a61bf5b6"> 
    5060    <TestLinks> 
     
    6171    <TestLinks> 
    6272      <TestLink id="905e7e83-ac17-d164-7c00-332aee943ebf" name="testBrazilianCached" storage="test2008\bin\debug\test2008.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel,   PublicKeyToken=b03f5f7f11d50a3a" /> 
    63       <TestLink id="af486b6a-ffe8-d458-89c3-9fcd3f6ec404" name="testYield" storage="test2008\bin\debug\test2008.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel,   PublicKeyToken=b03f5f7f11d50a3a" /> 
     73      <TestLink id="6dedd105-7532-140b-2b82-37bc69a8d72c" name="testCachedFixed" storage="test2008\bin\debug\test2008.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel,   PublicKeyToken=b03f5f7f11d50a3a" /> 
    6474      <TestLink id="a7feffcc-db48-6ab4-df10-00a5494c44ea" name="testTheoretical" storage="test2008\bin\debug\test2008.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel,   PublicKeyToken=b03f5f7f11d50a3a" /> 
    6575      <TestLink id="2e159c46-764f-ad21-7b0f-676f2bfdc323" name="testCachedFloating" storage="test2008\bin\debug\test2008.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel,   PublicKeyToken=b03f5f7f11d50a3a" /> 
    6676      <TestLink id="ab3ac37e-d457-63de-2204-c9a25f55fec9" name="testCached" storage="test2008\bin\debug\test2008.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel,   PublicKeyToken=b03f5f7f11d50a3a" /> 
    67       <TestLink id="6dedd105-7532-140b-2b82-37bc69a8d72c" name="testCachedFixed" storage="test2008\bin\debug\test2008.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel,   PublicKeyToken=b03f5f7f11d50a3a" /> 
    6877      <TestLink id="d7571d29-ddb9-5b86-6135-2acbcc05515d" name="testCachedZero" storage="test2008\bin\debug\test2008.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel,   PublicKeyToken=b03f5f7f11d50a3a" /> 
     78      <TestLink id="af486b6a-ffe8-d458-89c3-9fcd3f6ec404" name="testYield" storage="test2008\bin\debug\test2008.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel,   PublicKeyToken=b03f5f7f11d50a3a" /> 
    6979    </TestLinks> 
    7080  </TestList> 
  • trunk/QLNet/QLNet/Pricingengines/vanilla/FDAmericanEngine.cs

    r162 r165  
    3030        - the correctness of the returned greeks is tested by reproducing numerical derivatives. 
    3131    */ 
    32     public class FDAmericanEngine : FDEngineAdapter<FDAmericanCondition<FDStepConditionEngine>, OneAssetOption.Engine,  
    33                                                     OneAssetOption.Arguments, OneAssetOption.Results> { 
     32    public class FDAmericanEngine : FDEngineAdapter<FDAmericanCondition<FDStepConditionEngine>, OneAssetOption.Engine, 
     33                                                    OneAssetOption.Arguments, OneAssetOption.Results>,  
     34                                    IFDEngine { 
     35        // required for generics 
     36        public FDAmericanEngine() { } 
     37 
    3438        public FDAmericanEngine(GeneralizedBlackScholesProcess process, int timeSteps, int gridPoints) 
    3539            : this(process, timeSteps, gridPoints, false) { } 
    3640        public FDAmericanEngine(GeneralizedBlackScholesProcess process, int timeSteps, int gridPoints, bool timeDependent)  
    3741            : base(process, timeSteps, gridPoints, timeDependent) { } 
     42 
     43        public IFDEngine factory(GeneralizedBlackScholesProcess process) { 
     44            return new FDAmericanEngine(process, 100, 100, false); 
     45        } 
    3846    } 
    3947} 
  • trunk/QLNet/QLNet/Pricingengines/vanilla/FDVanillaEngine.cs

    r164 r165  
    128128        } 
    129129 
    130         protected double getResidualTime() { 
     130        public double getResidualTime() { 
    131131            return process_.time(exerciseDate_); 
    132132        } 
     
    154154 
    155155 
     156    // this is the interface to allow generic use of FDAmericanEngine and FDShoutEngine 
     157    // those engines are shortcuts to FDEngineAdapter 
     158    public interface IFDEngine : IPricingEngine { 
     159        IFDEngine factory(GeneralizedBlackScholesProcess process); 
     160    } 
     161 
    156162    public class FDEngineAdapter<Base, Engine, ArgumentsType, ResultsType> 
    157163        : FDVanillaEngine, IGenericEngine<ArgumentsType, ResultsType> 
     
    163169        // a wrap-up of base engine 
    164170        Base optionBase; 
     171 
     172        // required for generics 
     173        public FDEngineAdapter() { } 
    165174 
    166175        //public FDEngineAdapter(GeneralizedBlackScholesProcess process, Size timeSteps=100, Size gridPoints=100, bool timeDependent = false) 
  • trunk/QLNet/QLNet/Pricingengines/vanilla/fdconditions.cs

    r164 r165  
    4747        public FDConditionEngineTemplate(GeneralizedBlackScholesProcess process, int timeSteps, int gridPoints, bool timeDependent) 
    4848            : base(process, timeSteps, gridPoints, timeDependent) { } 
    49  
    5049    } 
    5150 
     
    105104        public FDShoutCondition() { } 
    106105        // required for template inheritance 
    107         new public FDVanillaEngine factory(GeneralizedBlackScholesProcess process, 
    108                                            int timeSteps, int gridPoints, bool timeDependent) { 
     106        public override FDVanillaEngine factory(GeneralizedBlackScholesProcess process, 
     107                                                int timeSteps, int gridPoints, bool timeDependent) { 
    109108            return new FDShoutCondition<baseEngine>(process, timeSteps, gridPoints, timeDependent); 
    110109        } 
     
    113112        //        Size timeSteps = 100, Size gridPoints = 100, bool timeDependent = false) 
    114113        public FDShoutCondition(GeneralizedBlackScholesProcess process, int timeSteps, int gridPoints, bool timeDependent) 
    115             : base(process, timeSteps, gridPoints, timeDependent) { } 
     114            : base(process, timeSteps, gridPoints, timeDependent) { 
     115            engine_.setStepCondition(initializeStepConditionImpl); 
     116        } 
    116117 
    117118        //protected override void initializeStepCondition() { 
     
    121122        //} 
    122123        protected IStepCondition<Vector> initializeStepConditionImpl() { 
    123             double residualTime = getResidualTime(); 
     124            // the following to rely on process_ which is the same for engine and here 
     125            // therefore wrapping is not requried 
     126            double residualTime = engine_.getResidualTime(); 
    124127            double riskFreeRate = process_.riskFreeRate().link.zeroRate(residualTime, Compounding.Continuous).rate(); 
    125128 
    126129            //stepCondition_ = new ShoutCondition(intrinsicValues_.values(), residualTime, riskFreeRate); 
    127             return new ShoutCondition(intrinsicValues_.values(), residualTime, riskFreeRate); 
     130            return new ShoutCondition(engine_.intrinsicValues_.values(), residualTime, riskFreeRate); 
    128131        } 
    129132    } 
  • trunk/QLNet/QLNet/QLNet.csproj

    r161 r165  
    236236    <Compile Include="Pricingengines\vanilla\FDEuropeanEngine.cs" /> 
    237237    <Compile Include="Pricingengines\vanilla\FDMultiPeriodEngine.cs" /> 
     238    <Compile Include="Pricingengines\vanilla\FDShoutEngine.cs" /> 
    238239    <Compile Include="Pricingengines\vanilla\FDStepConditionEngine.cs" /> 
    239240    <Compile Include="Pricingengines\vanilla\FDVanillaEngine.cs" /> 
  • trunk/QLNet/Test2008/T_AmericanOption.cs

    r61 r165  
    11/* 
     2 Copyright (C) 2008 Siarhei Novik (snovik@gmail.com) 
    23 Copyright (C) 2008 Andrea Maggiulli 
    34   
     
    2425using QLNet; 
    2526 
    26 namespace TestSuite 
    27 
    28  
    29    public struct AmericanOptionData 
    30    { 
     27namespace TestSuite { 
     28    public struct AmericanOptionData { 
    3129      public Option.Type type; 
    3230      public double strike; 
     
    3735      public double v; // volatility 
    3836      public double result; // expected result 
     37 
    3938      public AmericanOptionData(Option.Type type_, 
    4039                         double strike_, 
     
    5756   } 
    5857 
    59    [TestClass()] 
    60    class T_AmericanOption 
    61    { 
    62                 public static YieldTermStructure flatRate(Date today, Quote forward, DayCounter dc) 
    63                 { 
    64                         //return new YieldTermStructure(new FlatForward(today, new Handle<Quote>(forward), dc)); 
    65          return null; 
    66       } 
    67  
    68                 public static YieldTermStructure flatRate(Date today, double forward, DayCounter dc) 
    69                 { 
    70                         //return flatRate(today, boost.shared_ptr<Quote>(new SimpleQuote(forward)), dc); 
    71          return null; 
    72       } 
    73  
    74       [TestMethod()] 
    75       public void testBaroneAdesiWhaleyValues() 
    76       { 
    77          AmericanOptionData[] values = { 
    78             new AmericanOptionData(Option.Type.Call, 100.00,  90.00, 0.10, 0.10, 0.10, 0.15,  0.0206) , 
    79             new AmericanOptionData(Option.Type.Call, 100.00, 100.00, 0.10, 0.10, 0.10, 0.15,  1.8771) , 
    80             new AmericanOptionData(Option.Type.Call, 100.00, 110.00, 0.10, 0.10, 0.10, 0.15, 10.0089) , 
    81             new AmericanOptionData(Option.Type.Call, 100.00,  90.00, 0.10, 0.10, 0.10, 0.25,  0.3159) , 
    82             new AmericanOptionData(Option.Type.Call, 100.00, 100.00, 0.10, 0.10, 0.10, 0.25,  3.1280) , 
    83             new AmericanOptionData(Option.Type.Call, 100.00, 110.00, 0.10, 0.10, 0.10, 0.25, 10.3919) , 
    84             new AmericanOptionData(Option.Type.Call, 100.00,  90.00, 0.10, 0.10, 0.10, 0.35,  0.9495) , 
    85             new AmericanOptionData(Option.Type.Call, 100.00, 100.00, 0.10, 0.10, 0.10, 0.35,  4.3777) , 
    86             new AmericanOptionData(Option.Type.Call, 100.00, 110.00, 0.10, 0.10, 0.10, 0.35, 11.1679) , 
    87             new AmericanOptionData(Option.Type.Call, 100.00,  90.00, 0.10, 0.10, 0.50, 0.15,  0.8208) , 
    88             new AmericanOptionData(Option.Type.Call, 100.00, 100.00, 0.10, 0.10, 0.50, 0.15,  4.0842) , 
    89             new AmericanOptionData(Option.Type.Call, 100.00, 110.00, 0.10, 0.10, 0.50, 0.15, 10.8087) , 
    90             new AmericanOptionData(Option.Type.Call, 100.00,  90.00, 0.10, 0.10, 0.50, 0.25,  2.7437) , 
    91             new AmericanOptionData(Option.Type.Call, 100.00, 100.00, 0.10, 0.10, 0.50, 0.25,  6.8015) , 
    92             new AmericanOptionData(Option.Type.Call, 100.00, 110.00, 0.10, 0.10, 0.50, 0.25, 13.0170) , 
    93             new AmericanOptionData(Option.Type.Call, 100.00,  90.00, 0.10, 0.10, 0.50, 0.35,  5.0063) , 
    94             new AmericanOptionData(Option.Type.Call, 100.00, 100.00, 0.10, 0.10, 0.50, 0.35,  9.5106) , 
    95             new AmericanOptionData(Option.Type.Call, 100.00, 110.00, 0.10, 0.10, 0.50, 0.35, 15.5689) , 
    96             new AmericanOptionData(Option.Type.Put,  100.00,  90.00, 0.10, 0.10, 0.10, 0.15, 10.0000) , 
    97             new AmericanOptionData(Option.Type.Put,  100.00, 100.00, 0.10, 0.10, 0.10, 0.15,  1.8770) , 
    98             new AmericanOptionData(Option.Type.Put,  100.00, 110.00, 0.10, 0.10, 0.10, 0.15,  0.0410) , 
    99             new AmericanOptionData(Option.Type.Put,  100.00,  90.00, 0.10, 0.10, 0.10, 0.25, 10.2533) , 
    100             new AmericanOptionData(Option.Type.Put,  100.00, 100.00, 0.10, 0.10, 0.10, 0.25,  3.1277) , 
    101             new AmericanOptionData(Option.Type.Put,  100.00, 110.00, 0.10, 0.10, 0.10, 0.25,  0.4562) , 
    102             new AmericanOptionData(Option.Type.Put,  100.00,  90.00, 0.10, 0.10, 0.10, 0.35, 10.8787) , 
    103             new AmericanOptionData(Option.Type.Put,  100.00, 100.00, 0.10, 0.10, 0.10, 0.35,  4.3777) , 
    104             new AmericanOptionData(Option.Type.Put,  100.00, 110.00, 0.10, 0.10, 0.10, 0.35,  1.2402) , 
    105             new AmericanOptionData(Option.Type.Put,  100.00,  90.00, 0.10, 0.10, 0.50, 0.15, 10.5595) , 
    106             new AmericanOptionData(Option.Type.Put,  100.00, 100.00, 0.10, 0.10, 0.50, 0.15,  4.0842) , 
    107             new AmericanOptionData(Option.Type.Put,  100.00, 110.00, 0.10, 0.10, 0.50, 0.15,  1.0822) , 
    108             new AmericanOptionData(Option.Type.Put,  100.00,  90.00, 0.10, 0.10, 0.50, 0.25, 12.4419) , 
    109             new AmericanOptionData(Option.Type.Put,  100.00, 100.00, 0.10, 0.10, 0.50, 0.25,  6.8014) , 
    110             new AmericanOptionData(Option.Type.Put,  100.00, 110.00, 0.10, 0.10, 0.50, 0.25,  3.3226) , 
    111             new AmericanOptionData(Option.Type.Put,  100.00,  90.00, 0.10, 0.10, 0.50, 0.35, 14.6945) , 
    112             new AmericanOptionData(Option.Type.Put,  100.00, 100.00, 0.10, 0.10, 0.50, 0.35,  9.5104) , 
    113             new AmericanOptionData(Option.Type.Put,  100.00, 110.00, 0.10, 0.10, 0.50, 0.35,  5.8823)}; 
    114  
    115           Date today = Date.Today; 
    116           DayCounter dc = new Actual360(); 
    117           SimpleQuote spot = new SimpleQuote(0.0); 
    118           SimpleQuote qRate = new SimpleQuote(0.0); 
    119           YieldTermStructure qTS = flatRate(today, qRate, dc); 
    120  
    121  
    122  
    123       } 
     58    [TestClass()] 
     59    public class T_AmericanOption { 
     60 
     61            /* The data below are from 
     62           An Approximate Formula for Pricing American Options 
     63           Journal of Derivatives Winter 1999 
     64           Ju, N. 
     65        */ 
     66        AmericanOptionData[] juValues = new AmericanOptionData[] { 
     67            //        type, strike,   spot,    q,    r,    t,     vol,   value, tol 
     68            // These values are from Exhibit 3 - Short dated Put Options 
     69            new AmericanOptionData( Option.Type.Put, 35.00,   40.00,  0.0,  0.0488, 0.0833,  0.2,  0.006 ), 
     70            new AmericanOptionData( Option.Type.Put, 35.00,   40.00,  0.0,  0.0488, 0.3333,  0.2,  0.201 ), 
     71            new AmericanOptionData( Option.Type.Put, 35.00,   40.00,  0.0,  0.0488, 0.5833,  0.2,  0.433 ), 
     72 
     73            new AmericanOptionData( Option.Type.Put, 40.00,   40.00,  0.0,  0.0488, 0.0833,  0.2,  0.851 ), 
     74            new AmericanOptionData( Option.Type.Put, 40.00,   40.00,  0.0,  0.0488, 0.3333,  0.2,  1.576 ), 
     75            new AmericanOptionData( Option.Type.Put, 40.00,   40.00,  0.0,  0.0488, 0.5833,  0.2,  1.984 ), 
     76 
     77            new AmericanOptionData( Option.Type.Put, 45.00,   40.00,  0.0,  0.0488, 0.0833,  0.2,  5.000 ), 
     78            new AmericanOptionData( Option.Type.Put, 45.00,   40.00,  0.0,  0.0488, 0.3333,  0.2,  5.084 ), 
     79            new AmericanOptionData( Option.Type.Put, 45.00,   40.00,  0.0,  0.0488, 0.5833,  0.2,  5.260 ), 
     80 
     81            new AmericanOptionData( Option.Type.Put, 35.00,   40.00,  0.0,  0.0488, 0.0833,  0.3,  0.078 ), 
     82            new AmericanOptionData( Option.Type.Put, 35.00,   40.00,  0.0,  0.0488, 0.3333,  0.3,  0.697 ), 
     83            new AmericanOptionData( Option.Type.Put, 35.00,   40.00,  0.0,  0.0488, 0.5833,  0.3,  1.218 ), 
     84 
     85            new AmericanOptionData( Option.Type.Put, 40.00,   40.00,  0.0,  0.0488, 0.0833,  0.3,  1.309 ), 
     86            new AmericanOptionData( Option.Type.Put, 40.00,   40.00,  0.0,  0.0488, 0.3333,  0.3,  2.477 ), 
     87            new AmericanOptionData( Option.Type.Put, 40.00,   40.00,  0.0,  0.0488, 0.5833,  0.3,  3.161 ), 
     88 
     89            new AmericanOptionData( Option.Type.Put, 45.00,   40.00,  0.0,  0.0488, 0.0833,  0.3,  5.059 ), 
     90            new AmericanOptionData( Option.Type.Put, 45.00,   40.00,  0.0,  0.0488, 0.3333,  0.3,  5.699 ), 
     91            new AmericanOptionData( Option.Type.Put, 45.00,   40.00,  0.0,  0.0488, 0.5833,  0.3,  6.231 ), 
     92 
     93            new AmericanOptionData( Option.Type.Put, 35.00,   40.00,  0.0,  0.0488, 0.0833,  0.4,  0.247 ), 
     94            new AmericanOptionData( Option.Type.Put, 35.00,   40.00,  0.0,  0.0488, 0.3333,  0.4,  1.344 ), 
     95            new AmericanOptionData( Option.Type.Put, 35.00,   40.00,  0.0,  0.0488, 0.5833,  0.4,  2.150 ), 
     96 
     97            new AmericanOptionData( Option.Type.Put, 40.00,   40.00,  0.0,  0.0488, 0.0833,  0.4,  1.767 ), 
     98            new AmericanOptionData( Option.Type.Put, 40.00,   40.00,  0.0,  0.0488, 0.3333,  0.4,  3.381 ), 
     99            new AmericanOptionData( Option.Type.Put, 40.00,   40.00,  0.0,  0.0488, 0.5833,  0.4,  4.342 ), 
     100 
     101            new AmericanOptionData( Option.Type.Put, 45.00,   40.00,  0.0,  0.0488, 0.0833,  0.4,  5.288 ), 
     102            new AmericanOptionData( Option.Type.Put, 45.00,   40.00,  0.0,  0.0488, 0.3333,  0.4,  6.501 ), 
     103            new AmericanOptionData( Option.Type.Put, 45.00,   40.00,  0.0,  0.0488, 0.5833,  0.4,  7.367 ), 
     104 
     105            // Type in Exhibits 4 and 5 if you have some spare time ;-) 
     106 
     107            //        type, strike,   spot,    q,    r,    t,     vol,   value, tol 
     108            // values from Exhibit 6 - Long dated Call Options with dividends 
     109            new AmericanOptionData( Option.Type.Call, 100.00,   80.00,  0.07,  0.03, 3.0,  0.2,   2.605 ), 
     110            new AmericanOptionData( Option.Type.Call, 100.00,   90.00,  0.07,  0.03, 3.0,  0.2,   5.182 ), 
     111            new AmericanOptionData( Option.Type.Call, 100.00,  100.00,  0.07,  0.03, 3.0,  0.2,   9.065 ), 
     112            new AmericanOptionData( Option.Type.Call, 100.00,  110.00,  0.07,  0.03, 3.0,  0.2,  14.430 ), 
     113            new AmericanOptionData( Option.Type.Call, 100.00,  120.00,  0.07,  0.03, 3.0,  0.2,  21.398 ), 
     114 
     115            new AmericanOptionData( Option.Type.Call, 100.00,   80.00,  0.07,  0.03, 3.0,  0.4,  11.336 ), 
     116            new AmericanOptionData( Option.Type.Call, 100.00,   90.00,  0.07,  0.03, 3.0,  0.4,  15.711 ), 
     117            new AmericanOptionData( Option.Type.Call, 100.00,  100.00,  0.07,  0.03, 3.0,  0.4,  20.760 ), 
     118            new AmericanOptionData( Option.Type.Call, 100.00,  110.00,  0.07,  0.03, 3.0,  0.4,  26.440 ), 
     119            new AmericanOptionData( Option.Type.Call, 100.00,  120.00,  0.07,  0.03, 3.0,  0.4,  32.709 ), 
     120 
     121            new AmericanOptionData( Option.Type.Call, 100.00,   80.00,  0.07,  0.00001, 3.0,  0.3,   5.552 ), 
     122            new AmericanOptionData( Option.Type.Call, 100.00,   90.00,  0.07,  0.00001, 3.0,  0.3,   8.868 ), 
     123            new AmericanOptionData( Option.Type.Call, 100.00,  100.00,  0.07,  0.00001, 3.0,  0.3,  13.158 ), 
     124            new AmericanOptionData( Option.Type.Call, 100.00,  110.00,  0.07,  0.00001, 3.0,  0.3,  18.458 ), 
     125            new AmericanOptionData( Option.Type.Call, 100.00,  120.00,  0.07,  0.00001, 3.0,  0.3,  24.786 ), 
     126 
     127            new AmericanOptionData( Option.Type.Call, 100.00,   80.00,  0.03,  0.07, 3.0,  0.3,  12.177 ), 
     128            new AmericanOptionData( Option.Type.Call, 100.00,   90.00,  0.03,  0.07, 3.0,  0.3,  17.411 ), 
     129            new AmericanOptionData( Option.Type.Call, 100.00,  100.00,  0.03,  0.07, 3.0,  0.3,  23.402 ), 
     130            new AmericanOptionData( Option.Type.Call, 100.00,  110.00,  0.03,  0.07, 3.0,  0.3,  30.028 ), 
     131            new AmericanOptionData( Option.Type.Call, 100.00,  120.00,  0.03,  0.07, 3.0,  0.3,  37.177 ) 
     132        }; 
     133 
     134        [TestMethod()] 
     135        public void testBaroneAdesiWhaleyValues() { 
     136            // ("Testing Barone-Adesi and Whaley approximation for American options..."); 
     137 
     138            /* The data below are from 
     139               "Option pricing formulas", E.G. Haug, McGraw-Hill 1998 pag 24 
     140 
     141               The following values were replicated only up to the second digit 
     142               by the VB code provided by Haug, which was used as base for the 
     143               C++ implementation 
     144 
     145            */ 
     146            AmericanOptionData[] values = { 
     147                new AmericanOptionData(Option.Type.Call, 100.00,  90.00, 0.10, 0.10, 0.10, 0.15,  0.0206) , 
     148                new AmericanOptionData(Option.Type.Call, 100.00, 100.00, 0.10, 0.10, 0.10, 0.15,  1.8771) , 
     149                new AmericanOptionData(Option.Type.Call, 100.00, 110.00, 0.10, 0.10, 0.10, 0.15, 10.0089) , 
     150                new AmericanOptionData(Option.Type.Call, 100.00,  90.00, 0.10, 0.10, 0.10, 0.25,  0.3159) , 
     151                new AmericanOptionData(Option.Type.Call, 100.00, 100.00, 0.10, 0.10, 0.10, 0.25,  3.1280) , 
     152                new AmericanOptionData(Option.Type.Call, 100.00, 110.00, 0.10, 0.10, 0.10, 0.25, 10.3919) , 
     153                new AmericanOptionData(Option.Type.Call, 100.00,  90.00, 0.10, 0.10, 0.10, 0.35,  0.9495) , 
     154                new AmericanOptionData(Option.Type.Call, 100.00, 100.00, 0.10, 0.10, 0.10, 0.35,  4.3777) , 
     155                new AmericanOptionData(Option.Type.Call, 100.00, 110.00, 0.10, 0.10, 0.10, 0.35, 11.1679) , 
     156                new AmericanOptionData(Option.Type.Call, 100.00,  90.00, 0.10, 0.10, 0.50, 0.15,  0.8208) , 
     157                new AmericanOptionData(Option.Type.Call, 100.00, 100.00, 0.10, 0.10, 0.50, 0.15,  4.0842) , 
     158                new AmericanOptionData(Option.Type.Call, 100.00, 110.00, 0.10, 0.10, 0.50, 0.15, 10.8087) , 
     159                new AmericanOptionData(Option.Type.Call, 100.00,  90.00, 0.10, 0.10, 0.50, 0.25,  2.7437) , 
     160                new AmericanOptionData(Option.Type.Call, 100.00, 100.00, 0.10, 0.10, 0.50, 0.25,  6.8015) , 
     161                new AmericanOptionData(Option.Type.Call, 100.00, 110.00, 0.10, 0.10, 0.50, 0.25, 13.0170) , 
     162                new AmericanOptionData(Option.Type.Call, 100.00,  90.00, 0.10, 0.10, 0.50, 0.35,  5.0063) , 
     163                new AmericanOptionData(Option.Type.Call, 100.00, 100.00, 0.10, 0.10, 0.50, 0.35,  9.5106) , 
     164                new AmericanOptionData(Option.Type.Call, 100.00, 110.00, 0.10, 0.10, 0.50, 0.35, 15.5689) , 
     165                new AmericanOptionData(Option.Type.Put,  100.00,  90.00, 0.10, 0.10, 0.10, 0.15, 10.0000) , 
     166                new AmericanOptionData(Option.Type.Put,  100.00, 100.00, 0.10, 0.10, 0.10, 0.15,  1.8770) , 
     167                new AmericanOptionData(Option.Type.Put,  100.00, 110.00, 0.10, 0.10, 0.10, 0.15,  0.0410) , 
     168                new AmericanOptionData(Option.Type.Put,  100.00,  90.00, 0.10, 0.10, 0.10, 0.25, 10.2533) , 
     169                new AmericanOptionData(Option.Type.Put,  100.00, 100.00, 0.10, 0.10, 0.10, 0.25,  3.1277) , 
     170                new AmericanOptionData(Option.Type.Put,  100.00, 110.00, 0.10, 0.10, 0.10, 0.25,  0.4562) , 
     171                new AmericanOptionData(Option.Type.Put,  100.00,  90.00, 0.10, 0.10, 0.10, 0.35, 10.8787) , 
     172                new AmericanOptionData(Option.Type.Put,  100.00, 100.00, 0.10, 0.10, 0.10, 0.35,  4.3777) , 
     173                new AmericanOptionData(Option.Type.Put,  100.00, 110.00, 0.10, 0.10, 0.10, 0.35,  1.2402) , 
     174                new AmericanOptionData(Option.Type.Put,  100.00,  90.00, 0.10, 0.10, 0.50, 0.15, 10.5595) , 
     175                new AmericanOptionData(Option.Type.Put,  100.00, 100.00, 0.10, 0.10, 0.50, 0.15,  4.0842) , 
     176                new AmericanOptionData(Option.Type.Put,  100.00, 110.00, 0.10, 0.10, 0.50, 0.15,  1.0822) , 
     177                new AmericanOptionData(Option.Type.Put,  100.00,  90.00, 0.10, 0.10, 0.50, 0.25, 12.4419) , 
     178                new AmericanOptionData(Option.Type.Put,  100.00, 100.00, 0.10, 0.10, 0.50, 0.25,  6.8014) , 
     179                new AmericanOptionData(Option.Type.Put,  100.00, 110.00, 0.10, 0.10, 0.50, 0.25,  3.3226) , 
     180                new AmericanOptionData(Option.Type.Put,  100.00,  90.00, 0.10, 0.10, 0.50, 0.35, 14.6945) , 
     181                new AmericanOptionData(Option.Type.Put,  100.00, 100.00, 0.10, 0.10, 0.50, 0.35,  9.5104) , 
     182                new AmericanOptionData(Option.Type.Put,  100.00, 110.00, 0.10, 0.10, 0.50, 0.35,  5.8823)}; 
     183 
     184            Date today = Date.Today; 
     185            DayCounter dc = new Actual360(); 
     186            SimpleQuote spot = new SimpleQuote(0.0); 
     187            SimpleQuote qRate = new SimpleQuote(0.0); 
     188            YieldTermStructure qTS = Utilities.flatRate(today, qRate, dc); 
     189 
     190            SimpleQuote rRate = new SimpleQuote(0.0); 
     191            YieldTermStructure rTS = Utilities.flatRate(today, rRate, dc); 
     192            SimpleQuote vol = new SimpleQuote(0.0); 
     193            BlackVolTermStructure volTS = Utilities.flatVol(today, vol, dc); 
     194 
     195            double tolerance = 3.0e-3; 
     196 
     197            for (int i=0; i<values.Length; i++) { 
     198 
     199                StrikedTypePayoff payoff = new PlainVanillaPayoff(values[i].type, values[i].strike); 
     200                Date exDate = today + Convert.ToInt32(values[i].t*360+0.5); 
     201                Exercise exercise = new AmericanExercise(today, exDate); 
     202 
     203                spot .setValue(values[i].s); 
     204                qRate.setValue(values[i].q); 
     205                rRate.setValue(values[i].r); 
     206                vol  .setValue(values[i].v); 
     207 
     208                BlackScholesMertonProcess stochProcess = new BlackScholesMertonProcess(new Handle<Quote>(spot), 
     209                                              new Handle<YieldTermStructure>(qTS), 
     210                                              new Handle<YieldTermStructure>(rTS), 
     211                                              new Handle<BlackVolTermStructure>(volTS)); 
     212 
     213                IPricingEngine engine = new BaroneAdesiWhaleyApproximationEngine(stochProcess); 
     214 
     215                VanillaOption option = new VanillaOption(payoff, exercise); 
     216                option.setPricingEngine(engine); 
     217 
     218                double calculated = option.NPV(); 
     219                double error = Math.Abs(calculated-values[i].result); 
     220                if (error > tolerance) { 
     221                    REPORT_FAILURE("value", payoff, exercise, values[i].s, values[i].q, 
     222                                   values[i].r, today, values[i].v, values[i].result, 
     223                                   calculated, error, tolerance); 
     224                } 
     225            } 
     226        } 
     227 
     228        [TestMethod()] 
     229        public void testBjerksundStenslandValues() { 
     230            // ("Testing Bjerksund and Stensland approximation for American options..."); 
     231 
     232            AmericanOptionData[] values = new AmericanOptionData[] { 
     233                //      type, strike,   spot,    q,    r,    t,  vol,   value, tol 
     234                // from "Option pricing formulas", Haug, McGraw-Hill 1998, pag 27 
     235              new AmericanOptionData(Option.Type.Call,  40.00,  42.00, 0.08, 0.04, 0.75, 0.35,  5.2704), 
     236                // from "Option pricing formulas", Haug, McGraw-Hill 1998, VBA code 
     237              new AmericanOptionData(Option.Type.Put,   40.00,  36.00, 0.00, 0.06, 1.00, 0.20,  4.4531) 
     238            }; 
     239 
     240            Date today = Date.Today; 
     241            DayCounter dc = new Actual360(); 
     242            SimpleQuote spot = new SimpleQuote(0.0); 
     243            SimpleQuote qRate = new SimpleQuote(0.0); 
     244            YieldTermStructure qTS = Utilities.flatRate(today, qRate, dc); 
     245 
     246            SimpleQuote rRate = new SimpleQuote(0.0); 
     247            YieldTermStructure rTS = Utilities.flatRate(today, rRate, dc); 
     248            SimpleQuote vol = new SimpleQuote(0.0); 
     249            BlackVolTermStructure volTS = Utilities.flatVol(today, vol, dc); 
     250 
     251            double tolerance = 3.0e-3; 
     252 
     253            for (int i=0; i<values.Length; i++) { 
     254 
     255                StrikedTypePayoff payoff = new PlainVanillaPayoff(values[i].type, values[i].strike); 
     256                Date exDate = today + Convert.ToInt32(values[i].t*360+0.5); 
     257                Exercise exercise = new AmericanExercise(today, exDate); 
     258 
     259                spot .setValue(values[i].s); 
     260                qRate.setValue(values[i].q); 
     261                rRate.setValue(values[i].r); 
     262                vol  .setValue(values[i].v); 
     263 
     264                BlackScholesMertonProcess stochProcess = new BlackScholesMertonProcess(new Handle<Quote>(spot), 
     265                                              new Handle<YieldTermStructure>(qTS), 
     266                                              new Handle<YieldTermStructure>(rTS), 
     267                                              new Handle<BlackVolTermStructure>(volTS)); 
     268 
     269                IPricingEngine engine = new BjerksundStenslandApproximationEngine(stochProcess); 
     270 
     271                VanillaOption option = new VanillaOption(payoff, exercise); 
     272                option.setPricingEngine(engine); 
     273 
     274                double calculated = option.NPV(); 
     275                double error = Math.Abs(calculated-values[i].result); 
     276                if (error > tolerance) { 
     277                    REPORT_FAILURE("value", payoff, exercise, values[i].s, values[i].q, 
     278                                   values[i].r, today, values[i].v, values[i].result, 
     279                                   calculated, error, tolerance); 
     280                } 
     281            } 
     282        } 
     283 
     284        [TestMethod()] 
     285        public void testJuValues() { 
     286 
     287            // ("Testing Ju approximation for American options..."); 
     288 
     289            Date today = Date.Today; 
     290            DayCounter dc = new Actual360(); 
     291            SimpleQuote spot = new SimpleQuote(0.0); 
     292            SimpleQuote qRate = new SimpleQuote(0.0); 
     293            YieldTermStructure qTS = Utilities.flatRate(today, qRate, dc); 
     294 
     295            SimpleQuote rRate = new SimpleQuote(0.0); 
     296            YieldTermStructure rTS = Utilities.flatRate(today, rRate, dc); 
     297            SimpleQuote vol = new SimpleQuote(0.0); 
     298            BlackVolTermStructure volTS = Utilities.flatVol(today, vol, dc); 
     299 
     300            double tolerance = 1.0e-3; 
     301 
     302            for (int i = 0; i < juValues.Length; i++) { 
     303 
     304                StrikedTypePayoff payoff = new PlainVanillaPayoff(juValues[i].type, juValues[i].strike); 
     305                Date exDate = today + Convert.ToInt32(juValues[i].t*360+0.5); 
     306                Exercise exercise = new AmericanExercise(today, exDate); 
     307 
     308                spot .setValue(juValues[i].s); 
     309                qRate.setValue(juValues[i].q); 
     310                rRate.setValue(juValues[i].r); 
     311                vol  .setValue(juValues[i].v); 
     312 
     313                BlackScholesMertonProcess stochProcess = new BlackScholesMertonProcess(new Handle<Quote>(spot), 
     314                                              new Handle<YieldTermStructure>(qTS), 
     315                                              new Handle<YieldTermStructure>(rTS), 
     316                                              new Handle<BlackVolTermStructure>(volTS)); 
     317 
     318                IPricingEngine engine = new JuQuadraticApproximationEngine(stochProcess); 
     319 
     320                VanillaOption option = new VanillaOption(payoff, exercise); 
     321                option.setPricingEngine(engine); 
     322 
     323                double calculated = option.NPV(); 
     324                double error = Math.Abs(calculated - juValues[i].result); 
     325                if (error > tolerance) { 
     326                    REPORT_FAILURE("value", payoff, exercise, juValues[i].s, juValues[i].q, 
     327                                   juValues[i].r, today, juValues[i].v, juValues[i].result, 
     328                                   calculated, error, tolerance); 
     329                } 
     330            } 
     331        } 
     332 
     333        [TestMethod()] 
     334        public void testFdValues() { 
     335 
     336            //("Testing finite-difference engine for American options..."); 
     337 
     338            Date today = Date.Today; 
     339            DayCounter dc = new Actual360(); 
     340            SimpleQuote spot = new SimpleQuote(0.0); 
     341            SimpleQuote qRate = new SimpleQuote(0.0); 
     342            YieldTermStructure qTS = Utilities.flatRate(today, qRate, dc); 
     343 
     344            SimpleQuote rRate = new SimpleQuote(0.0); 
     345            YieldTermStructure rTS = Utilities.flatRate(today, rRate, dc); 
     346            SimpleQuote vol = new SimpleQuote(0.0); 
     347            BlackVolTermStructure volTS = Utilities.flatVol(today, vol, dc); 
     348 
     349            double tolerance = 8.0e-2; 
     350 
     351            for (int i = 0; i < juValues.Length; i++) { 
     352 
     353                StrikedTypePayoff payoff = new PlainVanillaPayoff(juValues[i].type, juValues[i].strike); 
     354                Date exDate = today + Convert.ToInt32(juValues[i].t*360+0.5); 
     355                Exercise exercise = new AmericanExercise(today, exDate); 
     356 
     357                spot .setValue(juValues[i].s); 
     358                qRate.setValue(juValues[i].q); 
     359                rRate.setValue(juValues[i].r); 
     360                vol  .setValue(juValues[i].v); 
     361 
     362                BlackScholesMertonProcess stochProcess = new BlackScholesMertonProcess(new Handle<Quote>(spot), 
     363                                              new Handle<YieldTermStructure>(qTS), 
     364                                              new Handle<YieldTermStructure>(rTS), 
     365                                              new Handle<BlackVolTermStructure>(volTS)); 
     366 
     367                IPricingEngine engine = new FDAmericanEngine(stochProcess, 100,100); 
     368 
     369                VanillaOption option = new VanillaOption(payoff, exercise); 
     370                option.setPricingEngine(engine); 
     371 
     372                double calculated = option.NPV(); 
     373                double error = Math.Abs(calculated - juValues[i].result); 
     374                if (error > tolerance) { 
     375                    REPORT_FAILURE("value", payoff, exercise, juValues[i].s, juValues[i].q, 
     376                                   juValues[i].r, today, juValues[i].v, juValues[i].result, 
     377                                   calculated, error, tolerance); 
     378                } 
     379            } 
     380        } 
     381 
     382        public void testFdGreeks<Engine>() where Engine : IFDEngine, new() { 
     383 
     384            //SavedSettings backup; 
     385 
     386            Dictionary<string, double> calculated = new Dictionary<string,double>(),  
     387                expected = new Dictionary<string,double>(),  
     388                tolerance = new Dictionary<string,double>(); 
     389 
     390            tolerance.Add("delta", 7.0e-4); 
     391            tolerance.Add("gamma", 2.0e-4); 
     392            //tolerance["theta"]  = 1.0e-4; 
     393 
     394            Option.Type[] types = new Option.Type[] { Option.Type.Call, Option.Type.Put }; 
     395            double[] strikes = { 50.0, 99.5, 100.0, 100.5, 150.0 }; 
     396            double[] underlyings = { 100.0 }; 
     397            double[] qRates = { 0.04, 0.05, 0.06 }; 
     398            double[] rRates = { 0.01, 0.05, 0.15 }; 
     399            int[] years = { 1, 2 }; 
     400            double[] vols = { 0.11, 0.50, 1.20 }; 
     401 
     402            Date today = Date.Today; 
     403            Settings.setEvaluationDate(today); 
     404 
     405            DayCounter dc = new Actual360(); 
     406            SimpleQuote spot = new SimpleQuote(0.0); 
     407            SimpleQuote qRate = new SimpleQuote(0.0); 
     408            YieldTermStructure qTS = Utilities.flatRate(today, qRate, dc); 
     409 
     410            SimpleQuote rRate = new SimpleQuote(0.0); 
     411            YieldTermStructure rTS = Utilities.flatRate(today, rRate, dc); 
     412            SimpleQuote vol = new SimpleQuote(0.0); 
     413            BlackVolTermStructure volTS = Utilities.flatVol(today, vol, dc); 
     414 
     415            for (int i=0; i<types.Length; i++) { 
     416              for (int j=0; j<strikes.Length; j++) { 
     417                for (int k=0; k<years.Length; k++) { 
     418                    Date exDate = today + new Period(years[k], TimeUnit.Years); 
     419                    Exercise exercise = new AmericanExercise(today, exDate); 
     420                    StrikedTypePayoff payoff = new PlainVanillaPayoff(types[i], strikes[j]); 
     421                    BlackScholesMertonProcess stochProcess = new BlackScholesMertonProcess(new Handle<Quote>(spot), 
     422                                                  new Handle<YieldTermStructure>(qTS), 
     423                                                  new Handle<YieldTermStructure>(rTS), 
     424                                                  new Handle<BlackVolTermStructure>(volTS)); 
     425 
     426                    IPricingEngine engine = new Engine().factory(stochProcess); 
     427 
     428                    VanillaOption option = new VanillaOption(payoff, exercise); 
     429                    option.setPricingEngine(engine); 
     430 
     431                    for (int l=0; l<underlyings.Length; l++) { 
     432                      for (int m=0; m<qRates.Length; m++) { 
     433                        for (int n=0; n<rRates.Length; n++) { 
     434                          for (int p=0; p<vols.Length; p++) { 
     435                            double u = underlyings[l]; 
     436                            double q = qRates[m], 
     437                                 r = rRates[n]; 
     438                            double v = vols[p]; 
     439                            spot.setValue(u); 
     440                            qRate.setValue(q); 
     441                            rRate.setValue(r); 
     442                            vol.setValue(v); 
     443 
     444                            double value = option.NPV(); 
     445                            calculated.Add("delta", option.delta()); 
     446                            calculated.Add("gamma", option.gamma()); 
     447                            //calculated["theta"]  = option.theta(); 
     448 
     449                            if (value > spot.value()*1.0e-5) { 
     450                                // perturb spot and get delta and gamma 
     451                                double du = u*1.0e-4; 
     452                                spot.setValue(u+du); 
     453                                double value_p = option.NPV(), 
     454                                     delta_p = option.delta(); 
     455                                spot.setValue(u-du); 
     456                                double value_m = option.NPV(), 
     457                                     delta_m = option.delta(); 
     458                                spot.setValue(u); 
     459                                expected.Add("delta", (value_p - value_m)/(2*du)); 
     460                                expected.Add("gamma", (delta_p - delta_m)/(2*du)); 
     461 
     462                                /* 
     463                                // perturb date and get theta 
     464                                Time dT = dc.yearFraction(today-1, today+1); 
     465                                Settings::instance().setEvaluationDate(today-1); 
     466                                value_m = option.NPV(); 
     467                                Settings::instance().setEvaluationDate(today+1); 
     468                                value_p = option.NPV(); 
     469                                Settings::instance().setEvaluationDate(today); 
     470                                expected["theta"] = (value_p - value_m)/dT; 
     471                                */ 
     472 
     473                                // compare 
     474                                foreach (string greek in calculated.Keys) { 
     475                                    double expct = expected  [greek], 
     476                                        calcl = calculated[greek], 
     477                                        tol   = tolerance [greek]; 
     478                                    double error = Utilities.relativeError(expct,calcl,u); 
     479                                    if (error>tol) { 
     480                                        REPORT_FAILURE(greek, payoff, exercise, 
     481                                                       u, q, r, today, v, 
     482                                                       expct, calcl, error, tol); 
     483                                    } 
     484                                } 
     485                            } 
     486                            calculated.Clear(); 
     487                            expected.Clear(); 
     488                          } 
     489                        } 
     490                      } 
     491                    } 
     492                } 
     493              } 
     494            } 
     495        } 
     496 
     497        [TestMethod()] 
     498        public void testFdAmericanGreeks() { 
     499            //("Testing finite-differences American option greeks..."); 
     500            testFdGreeks<FDAmericanEngine>(); 
     501        } 
     502 
     503        [TestMethod()] 
     504        public void testFdShoutGreeks() { 
     505            // ("Testing finite-differences shout option greeks..."); 
     506            testFdGreeks<FDShoutEngine>(); 
     507        } 
     508 
     509        void REPORT_FAILURE(string greekName, StrikedTypePayoff payoff, Exercise exercise, double s, double q, double r, 
     510        Date today, double v, double expected, double calculated, double error, double tolerance) { 
     511            Assert.Fail(exercise + " " 
     512                   + payoff.optionType() + " option with " 
     513                   + payoff + " payoff:\n" 
     514                   + "    spot value:       " + s + "\n" 
     515                   + "    strike:           " + payoff.strike() + "\n" 
     516                   + "    dividend yield:   " + q + "\n" 
     517                   + "    risk-free rate:   " + r + "\n" 
     518                   + "    reference date:   " + today + "\n" 
     519                   + "    maturity:         " + exercise.lastDate() + "\n" 
     520                   + "    volatility:       " + v + "\n\n" 
     521                   + "    expected " + greekName + ":   " + expected + "\n" 
     522                   + "    calculated " + greekName + ": " + calculated + "\n" 
     523                   + "    error:            " + error + "\n" 
     524                   + "    tolerance:        " + tolerance); 
     525        } 
    124526   } 
    125527}