-
-
Notifications
You must be signed in to change notification settings - Fork 5.1k
Expand file tree
/
Copy pathOptionStrategyMatcherOptions.cs
More file actions
260 lines (238 loc) · 11.5 KB
/
Copy pathOptionStrategyMatcherOptions.cs
File metadata and controls
260 lines (238 loc) · 11.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
/*
* 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
{
/// <summary>
/// Defines options that influence how the matcher operates.
/// </summary>
/// <remarks>
/// 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 <see cref="IOptionPositionCollectionEnumerator"/> 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.
/// </remarks>
public class OptionStrategyMatcherOptions
{
/// <summary>
/// The maximum amount of time spent trying to find an optimal solution.
/// </summary>
public TimeSpan MaximumDuration { get; }
/// <summary>
/// The maximum number of matches to evaluate for the entire portfolio.
/// </summary>
public int MaximumSolutionCount { get; }
/// <summary>
/// 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).
/// </summary>
public IReadOnlyList<int> MaximumCountPerLeg { get; }
/// <summary>
/// The definitions to be used for matching.
/// </summary>
public IEnumerable<OptionStrategyDefinition> Definitions
=> _definitionEnumerator.Enumerate(_definitions);
/// <summary>
/// Objective function used to compare different match solutions for a given set of positions/definitions
/// </summary>
public IOptionStrategyMatchObjectiveFunction ObjectiveFunction { get; }
private readonly IReadOnlyList<OptionStrategyDefinition> _definitions;
private readonly IOptionPositionCollectionEnumerator _positionEnumerator;
private readonly IOptionStrategyDefinitionEnumerator _definitionEnumerator;
/// <summary>
/// Initializes a new instance of the <see cref="OptionStrategyMatcherOptions"/> class, providing
/// options that control the behavior of the <see cref="OptionStrategyMatcher"/>
/// </summary>
public OptionStrategyMatcherOptions(
IReadOnlyList<OptionStrategyDefinition> definitions,
IReadOnlyList<int> 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)
{
// by default we prefer solutions minimizing the uncovered short option quantity,
// a proxy for the margin required to hold the resulting position groups
objectiveFunction = new UncoveredShortQuantityOptionStrategyMatchObjectiveFunction();
}
if (positionEnumerator == null)
{
positionEnumerator = new DefaultOptionPositionCollectionEnumerator();
}
_definitions = definitions;
MaximumDuration = maximumDuration;
ObjectiveFunction = objectiveFunction;
MaximumCountPerLeg = maximumCountPerLeg;
_positionEnumerator = positionEnumerator;
_definitionEnumerator = definitionEnumerator;
MaximumSolutionCount = maximumSolutionCount;
}
/// <summary>
/// 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.
/// </summary>
public int GetMaximumLegMatches(int legIndex)
{
return MaximumCountPerLeg[legIndex];
}
/// <summary>
/// Enumerates the specified <paramref name="positions"/> according to the configured
/// <see cref="IOptionPositionCollectionEnumerator"/>
/// </summary>
public IEnumerable<OptionPosition> Enumerate(OptionPositionCollection positions)
{
return _positionEnumerator.Enumerate(positions);
}
/// <summary>
/// Creates a new <see cref="OptionStrategyMatcherOptions"/> with the specified <paramref name="definitions"/>,
/// with no limits of maximum matches per leg and default values for the remaining options
/// </summary>
public static OptionStrategyMatcherOptions ForDefinitions(params OptionStrategyDefinition[] definitions)
{
return ForDefinitions(definitions.AsEnumerable());
}
/// <summary>
/// Creates a new <see cref="OptionStrategyMatcherOptions"/> with the specified <paramref name="definitions"/>,
/// with no limits of maximum matches per leg and default values for the remaining options
/// </summary>
public static OptionStrategyMatcherOptions ForDefinitions(IEnumerable<OptionStrategyDefinition> definitions)
{
var maximumCountPerLeg = new[] {int.MaxValue, int.MaxValue, int.MaxValue, int.MaxValue, int.MaxValue};
return new OptionStrategyMatcherOptions(definitions.ToList(), maximumCountPerLeg);
}
/// <summary>
/// Specifies the maximum time provided for obtaining an optimal solution.
/// </summary>
public OptionStrategyMatcherOptions WithMaximumDuration(TimeSpan duration)
{
return new OptionStrategyMatcherOptions(
_definitions,
MaximumCountPerLeg,
duration,
MaximumSolutionCount,
_definitionEnumerator,
ObjectiveFunction,
_positionEnumerator
);
}
/// <summary>
/// Specifies the maximum number of solutions to evaluate via the objective function.
/// </summary>
public OptionStrategyMatcherOptions WithMaximumSolutionCount(int count)
{
return new OptionStrategyMatcherOptions(
_definitions,
MaximumCountPerLeg,
MaximumDuration,
count,
_definitionEnumerator,
ObjectiveFunction,
_positionEnumerator
);
}
/// <summary>
/// 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.
/// </summary>
public OptionStrategyMatcherOptions WithMaximumCountPerLeg(IReadOnlyList<int> counts)
{
return new OptionStrategyMatcherOptions(
_definitions,
counts,
MaximumDuration,
MaximumSolutionCount,
_definitionEnumerator,
ObjectiveFunction,
_positionEnumerator
);
}
/// <summary>
/// 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.
/// </summary>
public OptionStrategyMatcherOptions WithObjectiveFunction(IOptionStrategyMatchObjectiveFunction function)
{
return new OptionStrategyMatcherOptions(
_definitions,
MaximumCountPerLeg,
MaximumDuration,
MaximumSolutionCount,
_definitionEnumerator,
function,
_positionEnumerator
);
}
/// <summary>
/// Specifies the order in which definitions are evaluated. Definitions evaluated sooner are more likely to
/// find matches than ones evaluated later.
/// </summary>
public OptionStrategyMatcherOptions WithDefinitionEnumerator(IOptionStrategyDefinitionEnumerator enumerator)
{
return new OptionStrategyMatcherOptions(
_definitions,
MaximumCountPerLeg,
MaximumDuration,
MaximumSolutionCount,
enumerator,
ObjectiveFunction,
_positionEnumerator
);
}
/// <summary>
/// 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.
/// </summary>
public OptionStrategyMatcherOptions WithPositionEnumerator(IOptionPositionCollectionEnumerator enumerator)
{
return new OptionStrategyMatcherOptions(
_definitions,
MaximumCountPerLeg,
MaximumDuration,
MaximumSolutionCount,
_definitionEnumerator,
ObjectiveFunction,
enumerator
);
}
}
}