Example #1
0
        public void ResultingPositionsAreCorrectWithUnderlying()
        {
            var positions = Empty.AddRange(
                Position(Call[100], -5),
                // should match 4 covered calls
                new OptionPosition(Underlying, 4)
            );

            var matches = CoveredCall.Match(positions).ToList();
            Assert.AreEqual(1, matches.Count);
            // underlying isn't included yet
            Assert.AreEqual(1, matches[0].Legs.Count);
            Assert.AreEqual(1, matches[0].Legs.Count(m => m.Position.Strike == 100 && m.Position.Quantity == -5));

            var strategy = matches[0].CreateStrategy();
            Assert.AreEqual(1, strategy.OptionLegs.Count);
            Assert.AreEqual(1, strategy.UnderlyingLegs.Count);
            Assert.AreEqual(1, strategy.OptionLegs.Count(m => m.Strike == 100 && m.Quantity == -4));
            Assert.AreEqual(1, strategy.UnderlyingLegs.Count(m => m.Quantity == 4));

            // assert the remaining positions are the expected ones
            positions = matches[0].RemoveFrom(positions);
            Assert.AreEqual(1, positions.Count);
            Assert.AreEqual(1, positions.Count(m => !m.IsUnderlying && m.Strike == 100 && m.Quantity == -1));
        }
Example #2
0
 /// <summary>
 /// Creates a new <see cref="OptionPositionCollection"/> from the specified enumerable of <paramref name="positions"/>
 /// </summary>
 public static OptionPositionCollection FromPositions(IEnumerable <IPosition> positions, decimal contractMultiplier)
 {
     return(Empty.AddRange(positions.Select(position =>
     {
         var quantity = (int)position.Quantity;
         if (position.Symbol.SecurityType.HasOptions())
         {
             quantity = (int)(quantity / contractMultiplier);
         }
         return new OptionPosition(position.Symbol, quantity);
     })));
 }
Example #3
0
        public void DoubleCountPositionsMatchingSamePositionMultipleTimesInDifferentMatches()
        {
            // this test aims to verify that we can match the same definition multiple times if positions allows
            // 1: -C110 +C105
            // 0: -C110 +C100
            // 2: -C115 +C105
            // 3: -C115 +C100
            var positions = Empty.AddRange(
                Position(Call[100], -1),
                Position(Call[105], -1),
                Position(Call[110]),
                Position(Call[115])
            );

            var matches = BearCallSpread.Match(positions).ToList();
            Assert.AreEqual(4, matches.Count);
            Assert.AreEqual(1, matches.Count(m => m.Legs[1].Position.Strike == 110 && m.Legs[0].Position.Strike == 105));
            Assert.AreEqual(1, matches.Count(m => m.Legs[1].Position.Strike == 110 && m.Legs[0].Position.Strike == 100));
            Assert.AreEqual(1, matches.Count(m => m.Legs[1].Position.Strike == 115 && m.Legs[0].Position.Strike == 105));
            Assert.AreEqual(1, matches.Count(m => m.Legs[1].Position.Strike == 115 && m.Legs[0].Position.Strike == 100));
        }
Example #4
0
        public void CoveredCall_MatchesMultipleTimes_ForEachUniqueShortCallContract()
        {
            // CoveredCall
            // 0: +1 underlying lot
            // 1: -1 Call
            // so we should match
            // (4U, -4C100)
            // (3U, -3C110)
            // (5U, -5C120)
            // (9U, -9C130)
            // (20U, -20C140)
            // OptionStrategyDefinition.Match produces ALL possible matches
            var positions = Empty.AddRange(Position(Underlying, +20),
                                           Position(Call[100], -4), Position(Put[105], -4),
                                           Position(Call[105], +4), Position(Put[110], +4),
                                           Position(Call[110], -3), Position(Put[115], -3),
                                           Position(Call[115], +3), Position(Put[120], +3),
                                           Position(Call[120], -5), Position(Put[125], -5),
                                           Position(Call[125], +5), Position(Put[130], +5),
                                           Position(Call[130], -9), Position(Put[135], -9),
                                           Position(Call[140], -21), Position(Put[145], -21)
                                           );

            // force lower strikes to be evaluated first to provide determinism for this test
            var options = OptionStrategyMatcherOptions.ForDefinitions(CoveredCall)
                          .WithPositionEnumerator(new FunctionalOptionPositionCollectionEnumerator(
                                                      pos => pos.OrderBy(p => p.IsUnderlying ? 0 : p.Strike)
                                                      ));

            var matches = CoveredCall.Match(options, positions).ToList();

            Assert.AreEqual(5, matches.Count);
            Assert.AreEqual(1, matches.Count(m => m.Multiplier == 4));
            Assert.AreEqual(1, matches.Count(m => m.Multiplier == 3));
            Assert.AreEqual(1, matches.Count(m => m.Multiplier == 5));
            Assert.AreEqual(1, matches.Count(m => m.Multiplier == 9));
            Assert.AreEqual(1, matches.Count(m => m.Multiplier == 20));
        }
Example #5
0
        public void ResultingPositionsAreCorrectNoUnderlying()
        {
            var positions = Empty.AddRange(
                Position(Call[100], 10),
                Position(Call[110], -20),
                Position(Call[120], 10)
            );

            var matches = ButterflyCall.Match(positions).ToList();
            Assert.AreEqual(1, matches.Count);
            Assert.AreEqual(3, matches[0].Legs.Count);
            Assert.AreEqual(1, matches[0].Legs.Count(m => m.Position.Strike == 100 && m.Position.Quantity == 10));
            Assert.AreEqual(1, matches[0].Legs.Count(m => m.Position.Strike == 110 && m.Position.Quantity == -20));
            Assert.AreEqual(1, matches[0].Legs.Count(m => m.Position.Strike == 120 && m.Position.Quantity == 10));

            // Now let add some extra option contracts which shouldn't match since they aren't enough
            positions = positions.Add(Position(Call[100], 5));
            positions = positions.Add(Position(Call[110], -5));

            matches = ButterflyCall.Match(positions).ToList();

            Assert.AreEqual(1, matches.Count);
            Assert.AreEqual(3, matches[0].Legs.Count);

            // assert the strategy size respects the matching multiplier
            var strategy = matches[0].CreateStrategy();
            Assert.AreEqual(1, strategy.OptionLegs.Count(m => m.Strike == 100 && m.Quantity == 10));
            Assert.AreEqual(1, strategy.OptionLegs.Count(m => m.Strike == 110 && m.Quantity == -20));
            Assert.AreEqual(1, strategy.OptionLegs.Count(m => m.Strike == 120 && m.Quantity == 10));

            // assert the remaining positions are the expected ones
            positions = matches[0].RemoveFrom(positions);
            Assert.AreEqual(2, positions.Count);
            Assert.AreEqual(1, positions.Count(m => m.Strike == 100 && m.Quantity == 5));
            Assert.AreEqual(1, positions.Count(m => m.Strike == 110 && m.Quantity == -5));
        }
Example #6
0
 /// <summary>
 /// Creates a new <see cref="OptionPositionCollection"/> from the specified enumerable of <paramref name="positions"/>
 /// </summary>
 public static OptionPositionCollection FromPositions(IEnumerable <OptionPosition> positions)
 {
     return(Empty.AddRange(positions));
 }