Пример #1
0
        public static void Compute(OptionPosition option)
        {
            IOptionsPricingModel pricingModel;

            switch (option.Model)
            {
            case OptionPricingModel.Binomial:
                pricingModel = new BinomialModel();
                break;

            case OptionPricingModel.BlackScholes:
                pricingModel = new BlackScholesModel();
                break;

            case OptionPricingModel.ExpliciteFiniteDifference:
                pricingModel = new ExpliciteFiniteDifferenceModel();
                break;

            case OptionPricingModel.Trinomial:
                pricingModel = new TrinomialModel();
                break;

            default:
                throw new InvalidOperationException($"No implementation for {option.Model}");
            }
            pricingModel.Compute(option);
        }
Пример #2
0
        public void TestVolSurface()
        {
            IVolatilitySurface volSurface = new VolatilitySurface("BHP", 4500M, DateTime.Today);
            ForwardExpiry      expiry1    = new ForwardExpiry(DateTime.Parse("01-Jan-2010"), 4200);
            ForwardExpiry      expiry2    = new ForwardExpiry(DateTime.Parse("01-Jan-2011"), 4400);
            OptionPosition     call1      = new OptionPosition("1245", 104, PositionType.Call);
            OptionPosition     put1       = new OptionPosition("1246", 1200, PositionType.Put);
            OptionPosition     call2      = new OptionPosition("1645", 180, PositionType.Call);
            OptionPosition     put2       = new OptionPosition("1646", 1300, PositionType.Put);
            Strike             strike1    = new Strike(4200, call1, put1);
            Strike             strike2    = new Strike(4000, call2, put2);
            IVolatilityPoint   point1     = new VolatilityPoint();

            point1.SetVolatility(0.30M, VolatilityState.Default());
            put1.SetVolatility(point1);
            call1.SetVolatility(point1);
            IVolatilityPoint point2 = new VolatilityPoint();

            point2.SetVolatility(0.40M, VolatilityState.Default());
            call2.SetVolatility(point2);
            put2.SetVolatility(point2);
            expiry1.AddStrike(strike1, true);
            expiry2.AddStrike(strike2, false);
            volSurface.AddExpiry(expiry1);
            volSurface.AddExpiry(expiry2);
            List <ForwardExpiry> forwardExpiries = volSurface.NodalExpiries.ToList();
            int n1 = forwardExpiries[0].Strikes.Count(item => item.NodalPoint);
            // int n2 = forwardExpiries[1].Strikes.Count(delegate(Strike item) { return item.NodalPoint == true; });
            int n2 = 0;

            Assert.AreEqual(1, n1 + n2);
        }
Пример #3
0
        public void None_CreatesOptionPosition_WithZeroQuantity()
        {
            var none = OptionPosition.None(Symbols.SPY);

            Assert.AreEqual(0, none.Quantity);
            Assert.AreEqual(Symbols.SPY, none.Symbol);
        }
Пример #4
0
        public void Compute(OptionPosition option) {
            var t = option.TimeToExpiry.Days / 365.0;
            var d1 = (Math.Log(option.UnderlyingPrice / option.Strike) + (option.InterestRate - option.DividendRate + option.Volatility * option.Volatility / 2) * t) / (option.Volatility * Math.Sqrt(t));
            var d2 = d1 - option.Volatility * Math.Sqrt(t);

            var sign = option.Side == Side.Buy ? 1 : -1;
            // when calculating option greeks keep in mind that we calculate greek for position, 
            // and that's why BS formulas for greeks must be multiplied by -1 in case we're selling options
            // so formulas for greeks are [sign * BSFormula]

            if (option.Type == OptionType.Call) {
                option.OptionPrice = option.UnderlyingPrice * Math.Pow(Math.E, -option.DividendRate * t) * NormalDistribution.Phi(d1) -
                                     option.Strike * Math.Pow(Math.E, -option.InterestRate * t) * NormalDistribution.Phi(d2);
                option.Delta = sign * Math.Pow(Math.E, -option.DividendRate * t) * NormalDistribution.Phi(d1);
                option.Theta = sign * (-(option.UnderlyingPrice * Math.Pow(Math.E, -option.DividendRate * t) * NormalDistribution.Density(d1) * option.Volatility) / (2 * Math.Sqrt(t)) -
                               option.InterestRate * option.Strike * Math.Pow(Math.E, -option.InterestRate * t) * NormalDistribution.Phi(d2));
                option.Rho = sign * option.Strike * t * Math.Pow(Math.E, -option.InterestRate * t) * NormalDistribution.Phi(d2);
            }
            else {
                option.OptionPrice = -option.UnderlyingPrice * Math.Pow(Math.E, -option.DividendRate * t) * NormalDistribution.Phi(-d1) +
                                     option.Strike * Math.Pow(Math.E, -option.InterestRate * t) * NormalDistribution.Phi(-d2);
                option.Delta = sign * Math.Pow(Math.E, -option.DividendRate * t) * (NormalDistribution.Phi(d1) - 1);
                option.Theta = sign * (-(option.UnderlyingPrice * Math.Pow(Math.E, -option.DividendRate * t) * NormalDistribution.Density(d1) * option.Volatility) / (2 * Math.Sqrt(t)) +
                                option.InterestRate * option.Strike * Math.Pow(Math.E, -option.InterestRate * t) * NormalDistribution.Phi(-d2));
                option.Rho = sign * (-1) * option.Strike * t * Math.Pow(Math.E, -option.InterestRate * t) * NormalDistribution.Phi(-d2);
            }

            option.Gamma = sign * Math.Pow(Math.E, -option.DividendRate * t) * NormalDistribution.Density(d1) / (option.UnderlyingPrice * option.Volatility * Math.Sqrt(t));
            option.Vega = sign * option.UnderlyingPrice * Math.Sqrt(t) * Math.Pow(Math.E, -option.DividendRate * t) * NormalDistribution.Density(d1);
        }
Пример #5
0
        public void Compute(OptionPosition option)
        {
            var t = option.TimeToExpiry.TotalDays / 365.0;

            if (Math.Abs(t) < Double.Epsilon)
            {
                return;
            }

            var d1 = Math.Log(option.UnderlyingPrice / option.Strike) + (option.InterestRate - option.DividendRate + Math.Pow(option.Volatility, 2)) / t;
            var d2 = d1 - option.Volatility * Math.Sqrt(t);

            // when calculating option greeks keep in mind that we calculate greek for position,
            // and that's why BS formulas for greeks must be multiplied by -1 in case we're selling options
            // so formulas for greeks are [sign * BSFormula]

            if (option.Type == OptionType.Call)
            {
                option.OptionPrice = option.UnderlyingPrice * NormalDistribution.Phi(d1) -
                                     option.Strike * Math.Exp(-option.InterestRate * t) * NormalDistribution.Phi(d2);

                option.Delta = Math.Exp(-option.DividendRate * t) * NormalDistribution.Phi(d1);

                option.Theta = -Math.Exp(-option.DividendRate * t) * option.UnderlyingPrice * NormalDistribution.Density(d1) *
                               option.Volatility / (2 * Math.Sqrt(t))
                               +
                               option.DividendRate * Math.Exp(-option.DividendRate * t) * option.UnderlyingPrice *
                               NormalDistribution.Phi(d1)
                               -
                               option.InterestRate * option.Strike * Math.Exp(-option.InterestRate * t) *
                               NormalDistribution.Phi(d2);

                option.Rho = t * option.Strike * Math.Exp(-option.InterestRate * t) * NormalDistribution.Phi(d2);
            }
            else
            {
                option.OptionPrice = -option.UnderlyingPrice * NormalDistribution.Phi(-d1) +
                                     option.Strike * Math.Exp(-option.InterestRate * t) * NormalDistribution.Phi(-d2);

                option.Delta = Math.Exp(-option.DividendRate * t) * (NormalDistribution.Phi(d1) - 1);

                option.Theta = -Math.Exp(-option.DividendRate * t) * option.UnderlyingPrice * NormalDistribution.Density(d1) *
                               option.Volatility / (2 * Math.Sqrt(t))
                               -
                               option.DividendRate * Math.Exp(-option.DividendRate * t) * option.UnderlyingPrice *
                               NormalDistribution.Phi(-d1)
                               +
                               option.InterestRate * option.Strike * Math.Exp(-option.InterestRate * t) *
                               NormalDistribution.Phi(-d2);

                option.Rho = -t *option.Strike *Math.Exp(-option.InterestRate *t) * NormalDistribution.Phi(-d2);
            }

            option.Gamma = Math.Exp(-option.DividendRate * t) * NormalDistribution.Density(d1) /
                           (option.UnderlyingPrice * option.Volatility * Math.Sqrt(t));
            option.Vega = Math.Exp(-option.DividendRate * t) * option.UnderlyingPrice * NormalDistribution.Density(d1) *
                          Math.Sqrt(t);

            SideHelper.FixGreeksAccordingToSide(option);
        }
Пример #6
0
        public void Negate_ReturnsOptionPosition_WithSameSymbolAndNegativeQuantity()
        {
            var position = new OptionPosition(Symbols.SPY, 42);
            var negated  = position.Negate();

            Assert.AreEqual(position.Symbol, negated.Symbol);
            Assert.AreEqual(-position.Quantity, negated.Quantity);
        }
Пример #7
0
        public void Initializes_OptionRight(PositionSide side)
        {
            // grab a random symbol and make it the correct right
            var quantity = (int)side;
            var position = new OptionPosition(Call[100], quantity);

            Assert.AreEqual(side, position.Side);
        }
Пример #8
0
 public static TestCase ExtraPosition(OptionStrategyDefinition definition, params OptionPosition[] positions)
 {
     // add a random position w/ the same underlying
     var maxStrike = positions.Where(p => p.Symbol.HasUnderlying).Max(p => p.Strike);
     var extra = new OptionPosition(positions[0].Symbol.WithStrike(maxStrike + 5m), 1);
     var pos = positions.Concat(new[] {extra}).ToList();
     return new TestCase(nameof(ExtraPosition), definition, pos, new[] {extra}, Array.Empty<OptionPosition>());
 }
Пример #9
0
        public void Initializes_OptionRight(OptionRight right)
        {
            // grab a random symbol and make it the correct right
            var symbol   = Call[100].WithRight(right);
            var position = new OptionPosition(symbol, 1);

            Assert.AreEqual(right, position.Right);
        }
Пример #10
0
        public void SubtractionOperator_SubtractsQuantity_WhenSymbolsMatch()
        {
            var left  = new OptionPosition(Symbols.SPY, 42);
            var right = new OptionPosition(Symbols.SPY, 1);
            var sum   = left - right;

            Assert.AreEqual(Symbols.SPY, sum.Symbol);
            Assert.AreEqual(41, sum.Quantity);
        }
Пример #11
0
        public void AdditionOperator_AddsQuantity_WhenSymbolsMatch()
        {
            var left  = new OptionPosition(Symbols.SPY, 42);
            var right = new OptionPosition(Symbols.SPY, 1);
            var sum   = left + right;

            Assert.AreEqual(Symbols.SPY, sum.Symbol);
            Assert.AreEqual(43, sum.Quantity);
        }
Пример #12
0
            public TestCase WithPosition(Symbol symbol, int quantity)
            {
                if (Position != default(OptionPosition))
                {
                    throw new InvalidOperationException($"Position has already been initialized: {Position}");
                }

                Position = new OptionPosition(symbol, quantity);
                return(this);
            }
 public void Compute(OptionPosition option)
 {
     // TODO : IMPLEMENT
     // option.OptionPrice =
     // option.Delta =
     // option.Gamma =
     // option.Vega =
     // option.Theta =
     // option.Rho =
 }
Пример #14
0
        public void SubtractionOperator_ThrowsInvalidOperationException_WhenSymbolsDoNotMatch()
        {
            OptionPosition difference;
            var            left  = new OptionPosition(Symbols.SPY, 42);
            var            right = new OptionPosition(Symbols.SPY_P_192_Feb19_2016, 1);

            Assert.Throws <InvalidOperationException>(
                () => difference = left - right
                );
        }
Пример #15
0
        public void AdditionOperator_DoesNotThrow_WhenOneSideEqualsDefault()
        {
            var value        = new OptionPosition(Symbols.SPY, 42);
            var defaultValue = default(OptionPosition);
            var valueFirst   = value + defaultValue;
            var defaultFirst = defaultValue + value;

            Assert.AreEqual(value, valueFirst);
            Assert.AreEqual(value, defaultFirst);
        }
Пример #16
0
        public void AdditionOperator_ThrowsInvalidOperationException_WhenSymbolsDoNotMatch()
        {
            OptionPosition sum;
            var            left  = new OptionPosition(Symbols.SPY, 42);
            var            right = new OptionPosition(Symbols.SPY_P_192_Feb19_2016, 1);

            Assert.Throws <InvalidOperationException>(
                () => sum = left + right
                );
        }
Пример #17
0
        private static string String(OptionPosition position)
        {
            var sign = position.Quantity > 0 ? "+" : "";

            var s = position.Symbol;
            var symbol = s.HasUnderlying
                ? $"{s.Underlying.Value}:{s.ID.OptionRight}@{s.ID.StrikePrice}:{s.ID.Date:MM-dd}"
                : s.Value;

            return $"{sign}{position.Quantity} {symbol}";
        }
Пример #18
0
        public static OptionPosition FixGreeksAccordingToSide(OptionPosition option)
        {
            var sign = option.Side == Side.Buy ? 1 : -1;

            option.Delta *= sign;
            option.Gamma *= sign;
            option.Theta *= sign;
            option.Vega  *= sign;
            option.Rho   *= sign;

            return(option);
        }
Пример #19
0
        public void Equality_IsDefinedUsing_SymbolAndQuantity()
        {
            var left  = new OptionPosition(Symbols.SPY, 42);
            var right = new OptionPosition(Symbols.SPY, 42);

            Assert.AreEqual(left, right);
            Assert.IsTrue(left == right);

            right = right.Negate();
            Assert.AreNotEqual(left, right);
            Assert.IsTrue(left != right);
        }
Пример #20
0
        public void Compute(OptionPosition option)
        {
            int    steps = option.TreeSteps;
            double s     = option.UnderlyingPrice;

            var t = option.TimeToExpiry.TotalDays / 365.0;

            if (Math.Abs(t) < Double.Epsilon)
            {
                return;
            }
            if (option.TreeSteps == 0)
            {
                return;
            }

            var deltaT = t / (double)steps;

            if (deltaT >= Math.Pow(option.Volatility, 2) / Math.Pow(option.InterestRate - option.DividendRate, 2))
            {
                return;
            }

            double u = Math.Exp(option.Volatility * Math.Sqrt(t));
            double d = 1 / u;

            var prices = GetPrices(option.Type == OptionType.Call, option.UnderlyingPrice, t, steps, option.Volatility,
                                   option.Strike, option.InterestRate, option.DividendRate);

            // x x x
            //   x x
            //     x


            option.OptionPrice = prices[0, 0];
            option.Delta       = (prices[1, 1] - prices[1, 0]) / (s * u - s * d);
            option.Gamma       = ((prices[2, 2] - prices[2, 1]) / (s * u * u - s * u * d) -
                                  (prices[2, 1] - prices[2, 0]) / (s * u * d - s * d * d)) / (0.5 * (s * u * u - s * d * d));
            option.Theta = (prices[2, 1] - prices[0, 0]) / (2 * deltaT);

            option.Vega =
                (GetPrices(option.Type == OptionType.Call, option.UnderlyingPrice, t, steps, option.Volatility * 1.01,
                           option.Strike, option.InterestRate, option.DividendRate)[0, 0]
                 - option.OptionPrice) / (option.Volatility * 0.01);

            option.Rho =
                (GetPrices(option.Type == OptionType.Call, option.UnderlyingPrice, t, steps, option.Volatility,
                           option.Strike, option.InterestRate * 1.01, option.DividendRate)[0, 0]
                 - option.OptionPrice) / (option.InterestRate * 0.01);

            SideHelper.FixGreeksAccordingToSide(option);
        }
Пример #21
0
        public void IsEmpty_ReturnsTrue_WhenCountIsZero(int count)
        {
            var positions = OptionPositionCollection.Empty;

            for (int i = 0; i < count; i++)
            {
                var position = new OptionPosition(Call[100 + i], 1 + i);
                positions = positions.Add(position);
            }

            Assert.AreEqual(count, positions.Count);
            Assert.AreEqual(count == 0, positions.IsEmpty);
        }
Пример #22
0
        public void MultiplyOperator_ScalesQuantity()
        {
            const int factor        = 2;
            var       position      = new OptionPosition(Symbols.SPY, 42);
            var       positionFirst = position * factor;

            Assert.AreEqual(position.Symbol, positionFirst.Symbol);
            Assert.AreEqual(factor * 42, positionFirst.Quantity);

            var factorFirst = factor * position;

            Assert.AreEqual(positionFirst, factorFirst);
        }
Пример #23
0
        public void Compute(OptionPosition option)
        {
            var t = option.TimeToExpiry.TotalDays / 365.0;

            if (Math.Abs(t) < Double.Epsilon)
            {
                return;
            }
            if (option.TreeSteps == 0)
            {
                return;
            }

            Func <double, double> getWithTime = x => GetPrice(option.Type == OptionType.Call, option.UnderlyingPrice, option.Strike,
                                                              option.Volatility, option.InterestRate, option.DividendRate, x, option.TreeSteps)[0, 0];
            Func <double, double> getWithVol = x => GetPrice(option.Type == OptionType.Call, option.UnderlyingPrice, option.Strike,
                                                             x, option.InterestRate, option.DividendRate, t, option.TreeSteps)[0, 0];
            Func <double, double> getWithR = x => GetPrice(option.Type == OptionType.Call, option.UnderlyingPrice, option.Strike,
                                                           option.Volatility, x, option.DividendRate, t, option.TreeSteps)[0, 0];

            var deltaT = t / (double)option.TreeSteps;

            double u = Math.Exp(option.Volatility * Math.Sqrt(2 * deltaT));
            double d = Math.Exp(-option.Volatility * Math.Sqrt(2 * deltaT));

            var prices = GetPrice(option.Type == OptionType.Call, option.UnderlyingPrice, option.Strike,
                                  option.Volatility, option.InterestRate, option.DividendRate, t, option.TreeSteps);

            option.OptionPrice = prices[0, 0];

            option.Delta = (prices[1, 2] - 2 * prices[1, 1] + prices[1, 0]) / (option.UnderlyingPrice * (u - d));

            option.Gamma = ((prices[2, 4] - 2 * prices[2, 3] + prices[2, 2]) / (Math.Pow(option.UnderlyingPrice * (u * u - u), 2)) -
                            (prices[2, 2] - 2 * prices[2, 1] + prices[2, 0]) / (Math.Pow(option.UnderlyingPrice * (d - d * d), 2))) /
                           (0.5 * (option.UnderlyingPrice * (u * u - d * d)));

            option.Theta = (getWithTime(t + deltaT) - getWithTime(t - deltaT)) / (2 * deltaT);

            double volDelta = option.Volatility * 0.01;

            option.Vega = (getWithVol(option.Volatility + volDelta) - getWithVol(option.Volatility - volDelta)) /
                          (2 * volDelta);

            double rDelta = option.InterestRate * 0.01;

            option.Rho = (getWithR(option.InterestRate + rDelta) - getWithR(option.InterestRate - rDelta)) /
                         (2 * rDelta);

            SideHelper.FixGreeksAccordingToSide(option);
        }
Пример #24
0
		internal static EOptionPosition SOptionPosition(OptionPosition x)
		{
			switch (x)
			{
			case OptionPosition.InTheMoney:
				return EOptionPosition.InTheMoney;
			case OptionPosition.AtTheMoney:
				return EOptionPosition.AtTheMoney;
			case OptionPosition.OutOfTheMoney:
				return EOptionPosition.OutOfTheMoney;
			default:
				throw new NotSupportedException();
			}
		}
Пример #25
0
 public PricingShellViewModel()
 {
     _currentOption = new OptionPosition();
     OptionStyles   =
         new ObservableCollection <OptionStyle>(Enum.GetValues(typeof(OptionStyle)).Cast <OptionStyle>());
     OptionExerciseTypes =
         new ObservableCollection <OptionExerciseType>(
             Enum.GetValues(typeof(OptionExerciseType)).Cast <OptionExerciseType>());
     OptionTypes   = new ObservableCollection <OptionType>(Enum.GetValues(typeof(OptionType)).Cast <OptionType>());
     PricingModels =
         new ObservableCollection <OptionPricingModel>(
             Enum.GetValues(typeof(OptionPricingModel)).Cast <OptionPricingModel>());
     computeThis();
     OptionsPortfolio.CollectionChanged += (sender, args) => computePortfolio();
 }
        public void Compute(OptionPosition option) {
            // initialise option parameters
            double S = option.UnderlyingPrice;
            double K = option.Strike;
            double sigma = option.Volatility;
            double r = option.InterestRate;
            double q = option.DividendRate;
            OptionType type = option.Type;
            OptionExerciseType exerciseType = option.ExerciseType;

            int nPriceSteps, nTimeSteps; // number of price and time steps in the lattice

            nPriceSteps = 300;
            double S_max = 2 * K;
            double dS = S_max / nPriceSteps;

            double t = option.TimeToExpiry.Days / 365.0;
            double dt = 0.9 / sigma / sigma / nPriceSteps / nPriceSteps; // for stability
            nTimeSteps = (int) Math.Floor(t / dt) + 1;
            dt = t / nTimeSteps; // interval between time steps

            double[,] optionPrice = createLattice(S, K, sigma, r, q, type, exerciseType, nTimeSteps, dt, nPriceSteps, dS);

            var sign = option.Side == Side.Buy ? 1 : -1;

            // find index such that S lies in [ index * dS, (index + 1) * dS ]
            int index = (int)Math.Floor(S / dS);
            double price = 0;
            // run 2-point Lagrange polynomial interpolation
            price = price + (S - dS * (index + 1)) / (dS * index - dS * (index + 1)) * optionPrice[0, index];
            price = price + (S - dS * index) / (dS * (index + 1) - dS * (index)) * optionPrice[0, index + 1];

            option.OptionPrice = price;

            option.Delta = sign * (optionPrice[0, index + 1] - optionPrice[0, index - 1]) / (2 * dS);
            option.Gamma = sign * (optionPrice[0, index + 1] - 2 * optionPrice[0, index] + optionPrice[0, index - 1]) / (dS * dS);
            option.Theta = (optionPrice[1, index] - optionPrice[0, index]) / dt;

            double delta = 0.001;

            double[,] priceDeltaVol = createLattice(S, K, (sigma + delta), r, q, type, exerciseType, nTimeSteps, dt, nPriceSteps, dS); // option price with a higher volatily for vega calculation
            price = (S - dS * (index + 1)) / (dS * index - dS * (index + 1)) * priceDeltaVol[0, index] + (S - dS * index) / (dS * (index + 1) - dS * (index)) * priceDeltaVol[0, index + 1]; // interpolate
            option.Vega = sign * (price - option.OptionPrice) / delta; // estimate option price sensitivity to volatility

            double[,] priceDeltaR = createLattice(S, K, sigma, (r + delta), q, type, exerciseType, nTimeSteps, dt, nPriceSteps, dS); // option price with a higher rate for rho calculation
            price = (S - dS * (index + 1)) / (dS * index - dS * (index + 1)) * priceDeltaR[0, index] + (S - dS * index) / (dS * (index + 1) - dS * (index)) * priceDeltaR[0, index + 1]; // interpolate
            option.Rho = sign * (price - option.OptionPrice) / delta; // estimate option price sensitivity to percent rate
        }
        private OptionPosition _Option(Option.Type optionType, double strikeLevel, double spotAtStrikeDate, DateTime maturity, DateTime tradeDate)
        {
            // Instanciate
            OptionPosition optionPosition = new OptionPosition(Payoff(optionType, strikeLevel) as StrikedTypePayoff, Exercise(maturity), tradeDate, spotAtStrikeDate, _dayCounter);

            // Set internal properties:
            // Levels
            optionPosition._strikeLevel  = strikeLevel;
            optionPosition._spotAtStrike = spotAtStrikeDate;

            // Dates
            // optionPosition.expiryDate = maturity;
            // optionPosition.tradeDate = tradeDate;

            // Return
            return(optionPosition);
        }
Пример #28
0
        internal static EOptionPosition SOptionPosition(OptionPosition x)
        {
            switch (x)
            {
            case OptionPosition.InTheMoney:
                return(EOptionPosition.InTheMoney);

            case OptionPosition.AtTheMoney:
                return(EOptionPosition.AtTheMoney);

            case OptionPosition.OutOfTheMoney:
                return(EOptionPosition.OutOfTheMoney);

            default:
                throw new NotSupportedException();
            }
        }
Пример #29
0
        public void Compute(OptionPosition option) {

            // initialise option parameters
            double S = option.UnderlyingPrice;
            double K = option.Strike;

            double sigma = option.Volatility;
            double r = option.InterestRate;
            double q = option.DividendRate;

            OptionType type = option.Type;
            OptionExerciseType exerciseType = option.ExerciseType;

            int nSteps = 1000; // number of steps in the binomial model

            double t = option.TimeToExpiry.Days / 365.0;
            double dt = t / nSteps; // time interval between steps

            

            double[,] lattice = createLattice(S, K, sigma, r, q, type, exerciseType, nSteps, dt);

            var sign = option.Side == Side.Buy ? 1 : -1;

            double upFactor = Math.Pow(Math.E, sigma * Math.Sqrt(dt));
            double downFactor = 1 / upFactor;

            option.OptionPrice = lattice[0, 0];

            option.Delta = sign * (lattice[1, 1] - lattice[1, 0]) / (option.UnderlyingPrice * (upFactor - downFactor));

            option.Gamma = sign * (((lattice[2, 2] - lattice[2, 1]) / (option.UnderlyingPrice * (upFactor * upFactor - upFactor * downFactor))) -
                                   ((lattice[2, 1] - lattice[2, 0]) / (option.UnderlyingPrice * (upFactor * downFactor - downFactor * downFactor)))) /
                                    (0.5 * option.UnderlyingPrice * (upFactor * upFactor - downFactor * downFactor)); 

            option.Theta = sign * (lattice[2, 1] - lattice[0, 0]) / (2 * dt);


            double delta = 0.001;
            double priceDeltaVol = createLattice(S, K, (sigma + delta), r, q, type, exerciseType, nSteps, dt)[0, 0]; // option price with a higher volatily for vega calculation
            option.Vega = sign * (priceDeltaVol - option.OptionPrice) / delta; // estimate option price sensitivity to volatility

            double priceDeltaR = createLattice(S, K, sigma, (r + delta), q, type, exerciseType, nSteps, dt)[0, 0]; // option price with a higher rate for rho calculation
            option.Rho = sign * (priceDeltaR - option.OptionPrice) / delta; // estimate option price sensitivity to percent rate
        }
Пример #30
0
        public static Stock CreateStock(EquityVolCalcTestData.Stock stock)
        {
            DateTime today    = XmlGetDate(stock.Date);
            decimal  spot     = Convert.ToDecimal(stock.Spot);
            DateTime baseDate = XmlGetDate(stock.RateCurve.BaseDate);

            DateTime[] rateDates = XmlGetDateArray(stock.RateCurve.DateArray);
            //Load rate curve
            String tp = stock.RateCurve.RateType;
            var    rc = new RateCurve(stock.RateCurve.Ccy, tp, baseDate, rateDates, stock.RateCurve.RateArray);
            // Load dividends
            var divs = (from div in stock.Dividends let exDate = XmlGetDate(div.ExDate) select new Dividend(exDate, Convert.ToDecimal(div.Amount))).ToList();
            //Load stock object
            var stock0 = new Stock(today, spot, stock.AssetId, stock.Name, rc, divs);
            var vol0   = new VolatilitySurface(stock.AssetId, spot, today);

            //Load vols
            stock0.VolatilitySurface = vol0;
            foreach (StockVolatilitySurfaceForwardExpiry exp in stock.VolatilitySurface.Expiries)
            {
                DateTime expDate = XmlGetDate(exp.ExpiryDate);
                Decimal  fwd     = Convert.ToDecimal(exp.FwdPrice);
                var      exp0    = new ForwardExpiry(expDate, fwd);
                // exp0.NodalPoint = System.Convert.ToBoolean(exp.NodalPoint);
                vol0.AddExpiry(exp0);

                foreach (StockVolatilitySurfaceForwardExpiryStrike str in exp.Strikes)
                {
                    var    call         = new OptionPosition();
                    var    put          = new OptionPosition();
                    double strikeprice0 = Convert.ToDouble(str.StrikePrice);
                    var    str0         = new Strike(strikeprice0, call, put, Units.Cents)
                    {
                        Moneyness = Convert.ToDouble(str.Moneyness)
                    };
                    exp0.AddStrike(str0, true);
                    var     vp  = new VolatilityPoint();
                    decimal vol = Convert.ToDecimal(str.Volatility.Value);
                    vp.SetVolatility(vol, VolatilityState.Default());
                    str0.SetVolatility(vp);
                }
            }
            return(stock0);
        }
Пример #31
0
        public void CreatesStrikePredicate()
        {
            var predicate = OptionStrategyLegPredicate.Create(
                (legs, p) => p.Strike < legs[0].Strike
                );

            var position    = new OptionPosition(Put[95m], 1);
            var positiveSet = new List <OptionPosition> {
                new OptionPosition(Put[100m], 1)
            };

            Assert.IsTrue(predicate.Matches(positiveSet, position));

            var negativeSet = new List <OptionPosition> {
                new OptionPosition(Put[90m], 1)
            };

            Assert.IsFalse(predicate.Matches(negativeSet, position));
        }
Пример #32
0
 public static void Compute(OptionPosition option) {
     IOptionsPricingModel pricingModel;
     switch (option.Model) {
         case OptionPricingModel.Binomial:
             pricingModel = new BinomialModel();
             break;
         case OptionPricingModel.BlackScholes:
             pricingModel = new BlackScholesModel();
             break;
         case OptionPricingModel.ExpliciteFiniteDifference:
             pricingModel = new ExpliciteFiniteDifferenceModel();
             break;
         case OptionPricingModel.Trinomial:
             pricingModel = new TrinomialModel();
             break;
         default:
             throw new InvalidOperationException($"No implementation for {option.Model}");
     }
     pricingModel.Compute(option);
 }
Пример #33
0
        private void ShowExample(object obj)
        {
            OptionsPortfolio.Clear();

            var option1 =
                new OptionPosition
            {
                ExpirationDateTime = DateTime.Now.AddYears(1),
                Strike             = 90,
                Type     = OptionType.Put,
                Side     = Side.Buy,
                Id       = _idCounter++,
                Quantity = 1
            };

            option1.PropertyChanged += EvaluatePortfolio;

            var option2 =
                new OptionPosition
            {
                Strike   = 100,
                Type     = OptionType.Call,
                Side     = Side.Sell,
                Id       = _idCounter++,
                Quantity = 1
            };

            option2.PropertyChanged += EvaluatePortfolio;

            option1.Compute();
            option2.Compute();

            option1.CostPrice = option1.PositionPrice;
            option2.CostPrice = option2.PositionPrice;

            OptionsPortfolio.Add(option1);
            OptionsPortfolio.Add(option2);
        }
Пример #34
0
        public void Compute(OptionPosition option)
        {
            var t = option.TimeToExpiry.Days / 365.0;
            // var d1 =
            // var d2 =

            var sign = option.Side == Side.Buy ? 1 : -1;

            // when calculating option greeks keep in mind that we calculate greek for position,
            // and that's why BS formulas for greeks must be multiplied by -1 in case we're selling options
            // so formulas for greeks are [sign * BSFormula]

            if (option.Type == OptionType.Call)
            {
                // option.OptionPrice =
                //option.Delta =
                //option.Theta =
                option.Rho = 555;
            }

            //option.Gamma =
            //option.Vega =
        }
Пример #35
0
 public static TestCase MissingPosition(OptionStrategyDefinition definition, OptionPosition missing, params OptionPosition[] positions)
 {
     return new TestCase(nameof(MissingPosition), definition, positions, Array.Empty<OptionPosition>(), new []{missing});
 }