Lean  $LEAN_TAG$
OptionStrategyMatcherOptions.cs
1 /*
2  * QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
3  * Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14 */
15 
16 using System;
17 using System.Collections.Generic;
18 using System.Linq;
19 
21 {
22  /// <summary>
23  /// Defines options that influence how the matcher operates.
24  /// </summary>
25  /// <remarks>
26  /// Many properties in this type are not implemented in the matcher but are provided to document
27  /// the types of things that can be added to the matcher in the future as necessary. Some of the
28  /// features contemplated in this class would require updating the various matching/filtering/slicing
29  /// functions to accept these options, or a particular property. This is the case for the enumerators
30  /// which would be used to prioritize which positions to try and match first. A great implementation
31  /// of the <see cref="IOptionPositionCollectionEnumerator"/> would be to yield positions with the
32  /// highest margin requirements first. At time of writing, the goal is to achieve a workable rev0,
33  /// and we can later improve the efficiency/optimization of the matching process.
34  /// </remarks>
36  {
37  /// <summary>
38  /// The maximum amount of time spent trying to find an optimal solution.
39  /// </summary>
40  public TimeSpan MaximumDuration { get; }
41 
42  /// <summary>
43  /// The maximum number of matches to evaluate for the entire portfolio.
44  /// </summary>
45  public int MaximumSolutionCount { get; }
46 
47  /// <summary>
48  /// Indexed by leg index, defines the max matches to evaluate per leg.
49  /// For example, MaximumCountPerLeg[1] is the max matches to evaluate
50  /// for the second leg (index=1).
51  /// </summary>
52  public IReadOnlyList<int> MaximumCountPerLeg { get; }
53 
54  /// <summary>
55  /// The definitions to be used for matching.
56  /// </summary>
57  public IEnumerable<OptionStrategyDefinition> Definitions
58  => _definitionEnumerator.Enumerate(_definitions);
59 
60  /// <summary>
61  /// Objective function used to compare different match solutions for a given set of positions/definitions
62  /// </summary>
64 
65  private readonly IReadOnlyList<OptionStrategyDefinition> _definitions;
66  private readonly IOptionPositionCollectionEnumerator _positionEnumerator;
67  private readonly IOptionStrategyDefinitionEnumerator _definitionEnumerator;
68 
69  /// <summary>
70  /// Initializes a new instance of the <see cref="OptionStrategyMatcherOptions"/> class, providing
71  /// options that control the behavior of the <see cref="OptionStrategyMatcher"/>
72  /// </summary>
74  IReadOnlyList<OptionStrategyDefinition> definitions,
75  IReadOnlyList<int> maximumCountPerLeg,
76  TimeSpan maximumDuration = default(TimeSpan),
77  int maximumSolutionCount = 100,
78  IOptionStrategyDefinitionEnumerator definitionEnumerator = null,
79  IOptionStrategyMatchObjectiveFunction objectiveFunction = null,
80  IOptionPositionCollectionEnumerator positionEnumerator = null
81  )
82  {
83  if (maximumDuration == default(TimeSpan))
84  {
85  maximumDuration = Time.OneMinute;
86  }
87 
88  if (definitionEnumerator == null)
89  {
90  // by default we want more complex option strategies to have matching priority
91  definitionEnumerator = new DescendingByLegCountOptionStrategyDefinitionEnumerator();
92  }
93 
94  if (objectiveFunction == null)
95  {
97  }
98 
99  if (positionEnumerator == null)
100  {
101  positionEnumerator = new DefaultOptionPositionCollectionEnumerator();
102  }
103 
104  _definitions = definitions;
105  MaximumDuration = maximumDuration;
106  ObjectiveFunction = objectiveFunction;
107  MaximumCountPerLeg = maximumCountPerLeg;
108  _positionEnumerator = positionEnumerator;
109  _definitionEnumerator = definitionEnumerator;
110  MaximumSolutionCount = maximumSolutionCount;
111  }
112 
113  /// <summary>
114  /// Gets the maximum number of leg matches to be evaluated. This is to limit evaluating exponential
115  /// numbers of potential matches as a result of large numbers of unique option positions for the same
116  /// underlying security.
117  /// </summary>
118  public int GetMaximumLegMatches(int legIndex)
119  {
120  return MaximumCountPerLeg[legIndex];
121  }
122 
123  /// <summary>
124  /// Enumerates the specified <paramref name="positions"/> according to the configured
125  /// <see cref="IOptionPositionCollectionEnumerator"/>
126  /// </summary>
127  public IEnumerable<OptionPosition> Enumerate(OptionPositionCollection positions)
128  {
129  return _positionEnumerator.Enumerate(positions);
130  }
131 
132  /// <summary>
133  /// Creates a new <see cref="OptionStrategyMatcherOptions"/> with the specified <paramref name="definitions"/>,
134  /// with no limits of maximum matches per leg and default values for the remaining options
135  /// </summary>
137  {
138  return ForDefinitions(definitions.AsEnumerable());
139  }
140 
141  /// <summary>
142  /// Creates a new <see cref="OptionStrategyMatcherOptions"/> with the specified <paramref name="definitions"/>,
143  /// with no limits of maximum matches per leg and default values for the remaining options
144  /// </summary>
145  public static OptionStrategyMatcherOptions ForDefinitions(IEnumerable<OptionStrategyDefinition> definitions)
146  {
147  var maximumCountPerLeg = new[] {int.MaxValue, int.MaxValue, int.MaxValue, int.MaxValue, int.MaxValue};
148  return new OptionStrategyMatcherOptions(definitions.ToList(), maximumCountPerLeg);
149  }
150 
151  /// <summary>
152  /// Specifies the maximum time provided for obtaining an optimal solution.
153  /// </summary>
155  {
156  return new OptionStrategyMatcherOptions(
157  _definitions,
159  duration,
161  _definitionEnumerator,
163  _positionEnumerator
164  );
165  }
166 
167  /// <summary>
168  /// Specifies the maximum number of solutions to evaluate via the objective function.
169  /// </summary>
171  {
172  return new OptionStrategyMatcherOptions(
173  _definitions,
176  count,
177  _definitionEnumerator,
179  _positionEnumerator
180  );
181  }
182 
183  /// <summary>
184  /// Specifies the maximum number of solutions per leg index in a solution. Matching is a recursive
185  /// process, for example, we'll find a very large number of positions to match the first leg. Matching
186  /// the second leg we'll see less, and third still even less. This is because each subsequent leg must
187  /// abide by all the previous legs. This parameter defines how many potential matches to evaluate at
188  /// each leg. For the first leg, we'll evaluate counts[0] matches. For the second leg we'll evaluate
189  /// counts[1] matches and so on. By decreasing this parameter we can evaluate more total, complete
190  /// solutions for the entire portfolio rather than evaluation every single permutation of matches for
191  /// a particular strategy definition, which grows in absurd exponential fashion as the portfolio grows.
192  /// </summary>
193  public OptionStrategyMatcherOptions WithMaximumCountPerLeg(IReadOnlyList<int> counts)
194  {
195  return new OptionStrategyMatcherOptions(
196  _definitions,
197  counts,
200  _definitionEnumerator,
202  _positionEnumerator
203  );
204  }
205 
206  /// <summary>
207  /// Specifies a function used to evaluate how desirable a particular solution is. A good implementation for
208  /// this would be to minimize the total margin required to hold all of the positions.
209  /// </summary>
211  {
212  return new OptionStrategyMatcherOptions(
213  _definitions,
217  _definitionEnumerator,
218  function,
219  _positionEnumerator
220  );
221  }
222 
223  /// <summary>
224  /// Specifies the order in which definitions are evaluated. Definitions evaluated sooner are more likely to
225  /// find matches than ones evaluated later.
226  /// </summary>
228  {
229  return new OptionStrategyMatcherOptions(
230  _definitions,
234  enumerator,
236  _positionEnumerator
237  );
238  }
239 
240  /// <summary>
241  /// Specifies the order in which positions are evaluated. Positions evaluated sooner are more likely to
242  /// find matches than ones evaluated later. A good implementation for this is its stand-alone margin required,
243  /// which would encourage the algorithm to match higher margin positions before matching lower margin positiosn.
244  /// </summary>
246  {
247  return new OptionStrategyMatcherOptions(
248  _definitions,
252  _definitionEnumerator,
254  enumerator
255  );
256  }
257  }
258 }