public SmileModelFitterTest()
        {
            VolatilityFunctionProvider <T> model = Model;
            T   data = ModelData;
            int n    = STRIKES.Length;

            _noisyVols = new double[n];
            _errors    = new double[n];
            _cleanVols = new double[n];
            Arrays.fill(_errors, 1e-4);
            for (int i = 0; i < n; i++)
            {
                _cleanVols[i] = model.volatility(F, STRIKES[i], TIME_TO_EXPIRY, data);
                _noisyVols[i] = _cleanVols[i] + UNIFORM.NextDouble() * _errors[i];
            }
            _fitter      = getFitter(F, STRIKES, TIME_TO_EXPIRY, _cleanVols, _errors, model);
            _nosiyFitter = getFitter(F, STRIKES, TIME_TO_EXPIRY, _noisyVols, _errors, model);
        }
        public virtual void horribleMarketDataTest()
        {
            double forward = 0.0059875;

            double[] strikes = new double[] { 0.0012499999999999734, 0.0024999999999999467, 0.003750000000000031, 0.0050000000000000044, 0.006249999999999978, 0.007499999999999951, 0.008750000000000036, 0.010000000000000009, 0.011249999999999982, 0.012499999999999956, 0.01375000000000004, 0.015000000000000013, 0.016249999999999987, 0.01749999999999996, 0.018750000000000044, 0.020000000000000018, 0.02124999999999999, 0.022499999999999964, 0.02375000000000005, 0.025000000000000022, 0.026249999999999996, 0.02749999999999997, 0.028750000000000053, 0.030000000000000027 };
            double   expiry  = 0.09041095890410959;

            double[] vols = new double[] { 2.7100433855959642, 1.5506135190088546, 0.9083977239618538, 0.738416513934868, 0.8806973450124451, 1.0906290439592792, 1.2461975189027226, 1.496275983572826, 1.5885915338673156, 1.4842142974195722, 1.7667347426399058, 1.4550288621444052, 1.0651798188736166, 1.143318270172714, 1.216215092528441, 1.2845258218014657, 1.3488224665755535, 1.9259326343836376, 1.9868728791190922, 2.0441767092857317, 2.0982583238541026, 2.1494622372820675, 2.198020785622251, 2.244237863291375 };
            int      n    = strikes.Length;

            double[] errors = new double[n];
            Arrays.fill(errors, 0.01);     //1% error
            SmileModelFitter <T> fitter = getFitter(forward, strikes, expiry, vols, errors, Model);
            LeastSquareResults   best   = null;
            BitArray             @fixed = new BitArray();

            for (int i = 0; i < 5; i++)
            {
                double[] start = RandomStartValues;

                //   int nStartPoints = start.length;
                LeastSquareResults lsRes = fitter.solve(DoubleArray.copyOf(start), @fixed);
                if (best == null)
                {
                    best = lsRes;
                }
                else
                {
                    if (lsRes.ChiSq < best.ChiSq)
                    {
                        best = lsRes;
                    }
                }
            }
            if (best != null)
            {
                assertTrue(best.ChiSq < 24000);   //average error 31.6% - not a good fit, but the data is horrible
            }
        }