/* * QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals. * Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ using System; using System.Collections.Generic; using System.Linq; namespace QuantConnect.Securities.Option.StrategyMatcher { /// /// Defines options that influence how the matcher operates. /// /// /// Many properties in this type are not implemented in the matcher but are provided to document /// the types of things that can be added to the matcher in the future as necessary. Some of the /// features contemplated in this class would require updating the various matching/filtering/slicing /// functions to accept these options, or a particular property. This is the case for the enumerators /// which would be used to prioritize which positions to try and match first. A great implementation /// of the would be to yield positions with the /// highest margin requirements first. At time of writing, the goal is to achieve a workable rev0, /// and we can later improve the efficiency/optimization of the matching process. /// public class OptionStrategyMatcherOptions { /// /// The maximum amount of time spent trying to find an optimal solution. /// public TimeSpan MaximumDuration { get; } /// /// The maximum number of matches to evaluate for the entire portfolio. /// public int MaximumSolutionCount { get; } /// /// Indexed by leg index, defines the max matches to evaluate per leg. /// For example, MaximumCountPerLeg[1] is the max matches to evaluate /// for the second leg (index=1). /// public IReadOnlyList MaximumCountPerLeg { get; } /// /// The definitions to be used for matching. /// public IEnumerable Definitions => _definitionEnumerator.Enumerate(_definitions); /// /// Objective function used to compare different match solutions for a given set of positions/definitions /// public IOptionStrategyMatchObjectiveFunction ObjectiveFunction { get; } private readonly IReadOnlyList _definitions; private readonly IOptionPositionCollectionEnumerator _positionEnumerator; private readonly IOptionStrategyDefinitionEnumerator _definitionEnumerator; /// /// Initializes a new instance of the class, providing /// options that control the behavior of the /// public OptionStrategyMatcherOptions( IReadOnlyList definitions, IReadOnlyList maximumCountPerLeg, TimeSpan maximumDuration = default(TimeSpan), int maximumSolutionCount = 100, IOptionStrategyDefinitionEnumerator definitionEnumerator = null, IOptionStrategyMatchObjectiveFunction objectiveFunction = null, IOptionPositionCollectionEnumerator positionEnumerator = null ) { if (maximumDuration == default(TimeSpan)) { maximumDuration = Time.OneMinute; } if (definitionEnumerator == null) { // by default we want more complex option strategies to have matching priority definitionEnumerator = new DescendingByLegCountOptionStrategyDefinitionEnumerator(); } if (objectiveFunction == null) { objectiveFunction = new UnmatchedPositionCountOptionStrategyMatchObjectiveFunction(); } if (positionEnumerator == null) { positionEnumerator = new DefaultOptionPositionCollectionEnumerator(); } _definitions = definitions; MaximumDuration = maximumDuration; ObjectiveFunction = objectiveFunction; MaximumCountPerLeg = maximumCountPerLeg; _positionEnumerator = positionEnumerator; _definitionEnumerator = definitionEnumerator; MaximumSolutionCount = maximumSolutionCount; } /// /// Gets the maximum number of leg matches to be evaluated. This is to limit evaluating exponential /// numbers of potential matches as a result of large numbers of unique option positions for the same /// underlying security. /// public int GetMaximumLegMatches(int legIndex) { return MaximumCountPerLeg[legIndex]; } /// /// Enumerates the specified according to the configured /// /// public IEnumerable Enumerate(OptionPositionCollection positions) { return _positionEnumerator.Enumerate(positions); } /// /// Creates a new with the specified , /// with no limits of maximum matches per leg and default values for the remaining options /// public static OptionStrategyMatcherOptions ForDefinitions(params OptionStrategyDefinition[] definitions) { return ForDefinitions(definitions.AsEnumerable()); } /// /// Creates a new with the specified , /// with no limits of maximum matches per leg and default values for the remaining options /// public static OptionStrategyMatcherOptions ForDefinitions(IEnumerable definitions) { var maximumCountPerLeg = new[] {int.MaxValue, int.MaxValue, int.MaxValue, int.MaxValue, int.MaxValue}; return new OptionStrategyMatcherOptions(definitions.ToList(), maximumCountPerLeg); } /// /// Specifies the maximum time provided for obtaining an optimal solution. /// public OptionStrategyMatcherOptions WithMaximumDuration(TimeSpan duration) { return new OptionStrategyMatcherOptions( _definitions, MaximumCountPerLeg, duration, MaximumSolutionCount, _definitionEnumerator, ObjectiveFunction, _positionEnumerator ); } /// /// Specifies the maximum number of solutions to evaluate via the objective function. /// public OptionStrategyMatcherOptions WithMaximumSolutionCount(int count) { return new OptionStrategyMatcherOptions( _definitions, MaximumCountPerLeg, MaximumDuration, count, _definitionEnumerator, ObjectiveFunction, _positionEnumerator ); } /// /// Specifies the maximum number of solutions per leg index in a solution. Matching is a recursive /// process, for example, we'll find a very large number of positions to match the first leg. Matching /// the second leg we'll see less, and third still even less. This is because each subsequent leg must /// abide by all the previous legs. This parameter defines how many potential matches to evaluate at /// each leg. For the first leg, we'll evaluate counts[0] matches. For the second leg we'll evaluate /// counts[1] matches and so on. By decreasing this parameter we can evaluate more total, complete /// solutions for the entire portfolio rather than evaluation every single permutation of matches for /// a particular strategy definition, which grows in absurd exponential fashion as the portfolio grows. /// public OptionStrategyMatcherOptions WithMaximumCountPerLeg(IReadOnlyList counts) { return new OptionStrategyMatcherOptions( _definitions, counts, MaximumDuration, MaximumSolutionCount, _definitionEnumerator, ObjectiveFunction, _positionEnumerator ); } /// /// Specifies a function used to evaluate how desirable a particular solution is. A good implementation for /// this would be to minimize the total margin required to hold all of the positions. /// public OptionStrategyMatcherOptions WithObjectiveFunction(IOptionStrategyMatchObjectiveFunction function) { return new OptionStrategyMatcherOptions( _definitions, MaximumCountPerLeg, MaximumDuration, MaximumSolutionCount, _definitionEnumerator, function, _positionEnumerator ); } /// /// Specifies the order in which definitions are evaluated. Definitions evaluated sooner are more likely to /// find matches than ones evaluated later. /// public OptionStrategyMatcherOptions WithDefinitionEnumerator(IOptionStrategyDefinitionEnumerator enumerator) { return new OptionStrategyMatcherOptions( _definitions, MaximumCountPerLeg, MaximumDuration, MaximumSolutionCount, enumerator, ObjectiveFunction, _positionEnumerator ); } /// /// Specifies the order in which positions are evaluated. Positions evaluated sooner are more likely to /// find matches than ones evaluated later. A good implementation for this is its stand-alone margin required, /// which would encourage the algorithm to match higher margin positions before matching lower margin positiosn. /// public OptionStrategyMatcherOptions WithPositionEnumerator(IOptionPositionCollectionEnumerator enumerator) { return new OptionStrategyMatcherOptions( _definitions, MaximumCountPerLeg, MaximumDuration, MaximumSolutionCount, _definitionEnumerator, ObjectiveFunction, enumerator ); } } }