예제 #1
0
 /// <summary>
 /// Yields all possible matches for this leg definition held within the collection of <paramref name="positions"/>
 /// </summary>
 /// <param name="options">Strategy matcher options guiding matching behaviors</param>
 /// <param name="legs">The preceding legs already matched for the parent strategy definition</param>
 /// <param name="positions">The remaining, unmatched positions available to be matched against</param>
 /// <returns>An enumerable of potential matches</returns>
 public IEnumerable <OptionStrategyLegDefinitionMatch> Match(
     OptionStrategyMatcherOptions options,
     IReadOnlyList <OptionPosition> legs,
     OptionPositionCollection positions
     )
 {
     foreach (var position in options.Enumerate(Filter(legs, positions, false)))
     {
         var multiplier = position.Quantity / Quantity;
         if (multiplier != 0)
         {
             yield return(new OptionStrategyLegDefinitionMatch(multiplier,
                                                               position.WithQuantity(multiplier * Quantity)
                                                               ));
         }
     }
 }
        private IEnumerable <OptionStrategyDefinitionMatch> Match(
            OptionStrategyMatcherOptions options,
            ImmutableList <OptionStrategyLegDefinitionMatch> legMatches,
            ImmutableList <OptionPosition> legPositions,
            OptionPositionCollection positions,
            int multiplier
            )
        {
            var nextLegIndex = legPositions.Count;

            if (nextLegIndex == Legs.Count)
            {
                if (nextLegIndex > 0)
                {
                    yield return(new OptionStrategyDefinitionMatch(this, legMatches, multiplier));
                }
            }
            else if (positions.Count >= LegCount - nextLegIndex)
            {
                // grab the next leg definition and perform the match, restricting total to configured maximum per leg
                var nextLeg     = Legs[nextLegIndex];
                var maxLegMatch = options.GetMaximumLegMatches(nextLegIndex);
                foreach (var legMatch in nextLeg.Match(options, legPositions, positions).Take(maxLegMatch))
                {
                    // add match to the match we're constructing and deduct matched position from positions collection
                    // we track the min multiplier in line so when we're done, we have the total number of matches for
                    // the matched set of positions in this 'thread' (OptionStrategy.Quantity)
                    foreach (var definitionMatch in Match(options,
                                                          legMatches.Add(legMatch),
                                                          legPositions.Add(legMatch.Position),
                                                          positions - legMatch.Position,
                                                          Math.Min(multiplier, legMatch.Multiplier)
                                                          ))
                    {
                        yield return(definitionMatch);
                    }
                }
            }
            else
            {
                // positions.Count < LegsCount indicates a failed match

                // could include partial matches, would allow an algorithm to determine if adding a
                // new position could help reduce overall margin exposure by completing a strategy
            }
        }
        /// <summary>
        /// Determines all possible matches for this definition using the provided <paramref name="positions"/>.
        /// This includes OVERLAPPING matches. It's up to the actual matcher to make decisions based on which
        /// matches to accept. This allows the matcher to prioritize matching certain positions over others.
        /// </summary>
        public IEnumerable <OptionStrategyDefinitionMatch> Match(
            OptionStrategyMatcherOptions options,
            OptionPositionCollection positions
            )
        {
            // TODO : Pass OptionStrategyMatcherOptions in and respect applicable options
            if (positions.Count < LegCount)
            {
                return(Enumerable.Empty <OptionStrategyDefinitionMatch>());
            }

            var multiplier = int.MaxValue;

            // first check underlying lots has correct sign and sufficient magnitude
            var underlyingLotsSign = Math.Sign(UnderlyingLots);

            if (underlyingLotsSign != 0)
            {
                var underlyingPositionSign = Math.Sign(positions.UnderlyingQuantity);
                if (underlyingLotsSign != underlyingPositionSign ||
                    Math.Abs(positions.UnderlyingQuantity) < Math.Abs(UnderlyingLots))
                {
                    return(Enumerable.Empty <OptionStrategyDefinitionMatch>());
                }

                // set multiplier for underlying
                multiplier = positions.UnderlyingQuantity / UnderlyingLots;
            }

            // TODO : Consider add OptionStrategyLegDefinition for underlying for consistency purposes.
            //        Might want to enforce that it's always the first leg definition as well for easier slicing.
            return(Match(options,
                         ImmutableList <OptionStrategyLegDefinitionMatch> .Empty,
                         ImmutableList <OptionPosition> .Empty,
                         positions,
                         multiplier
                         ).Distinct());
        }
예제 #4
0
 /// <summary>
 /// Initializes a new instance of the <see cref="OptionStrategyMatcher"/> class
 /// </summary>
 /// <param name="options">Specifies definitions and other options controlling the matcher</param>
 public OptionStrategyMatcher(OptionStrategyMatcherOptions options)
 {
     Options = options;
 }
 /// <summary>
 /// Determines all possible matches for this definition using the provided <paramref name="positions"/>.
 /// This includes OVERLAPPING matches. It's up to the actual matcher to make decisions based on which
 /// matches to accept. This allows the matcher to prioritize matching certain positions over others.
 /// </summary>
 public IEnumerable <OptionStrategyDefinitionMatch> Match(OptionPositionCollection positions)
 {
     return(Match(OptionStrategyMatcherOptions.ForDefinitions(this), positions));
 }
 /// <summary>
 /// Attempts to match the positions to this definition exactly once, by evaluating the enumerable and
 /// taking the first entry matched. If not match is found, then false is returned and <paramref name="match"/>
 /// will be null.
 /// </summary>
 public bool TryMatchOnce(OptionStrategyMatcherOptions options, OptionPositionCollection positions, out OptionStrategyDefinitionMatch match)
 {
     match = Match(options, positions).FirstOrDefault();
     return(match != null);
 }