Lean  $LEAN_TAG$
OptionChainUniverse.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 
17 using System;
18 using System.Linq;
21 using System.Collections.Generic;
23 
25 {
26  /// <summary>
27  /// Defines a universe for a single option chain
28  /// </summary>
30  {
31  private readonly OptionFilterUniverse _optionFilterUniverse;
32  // as an array to make it easy to prepend to selected symbols
33  private readonly Symbol[] _underlyingSymbol;
34 
35  /// <summary>
36  /// True if this universe filter can run async in the data stack
37  /// </summary>
38  public override bool Asynchronous
39  {
40  get
41  {
42  if (UniverseSettings.Asynchronous.HasValue)
43  {
44  return UniverseSettings.Asynchronous.Value;
45  }
46  return Option.ContractFilter.Asynchronous;
47  }
48  }
49 
50  /// <summary>
51  /// Initializes a new instance of the <see cref="OptionChainUniverse"/> class
52  /// </summary>
53  /// <param name="option">The canonical option chain security</param>
54  /// <param name="universeSettings">The universe settings to be used for new subscriptions</param>
55  public OptionChainUniverse(Option option,
56  UniverseSettings universeSettings)
57  : base(option.SubscriptionDataConfig)
58  {
59  Option = option;
60  UniverseSettings = universeSettings;
61  _underlyingSymbol = new[] { Option.Symbol.Underlying };
62  _optionFilterUniverse = new OptionFilterUniverse(Option);
63  }
64 
65  /// <summary>
66  /// The canonical option chain security
67  /// </summary>
68  public Option Option { get; }
69 
70  /// <summary>
71  /// Gets the settings used for subscriptons added for this universe
72  /// </summary>
73  public override UniverseSettings UniverseSettings
74  {
75  set
76  {
77  if (value != null)
78  {
79  // make sure data mode is raw
81  }
82  }
83  }
84 
85  /// <summary>
86  /// Performs universe selection using the data specified
87  /// </summary>
88  /// <param name="utcTime">The current utc time</param>
89  /// <param name="data">The symbols to remain in the universe</param>
90  /// <returns>The data that passes the filter</returns>
91  public override IEnumerable<Symbol> SelectSymbols(DateTime utcTime, BaseDataCollection data)
92  {
93  var localEndTime = utcTime.ConvertFromUtc(Option.Exchange.TimeZone);
94  // we will only update unique strikes when there is an exchange date change
95  _optionFilterUniverse.Refresh(data.Data.Cast<OptionUniverse>().ToList(), data.Underlying, localEndTime);
96 
97  var results = Option.ContractFilter.Filter(_optionFilterUniverse);
98 
99  // always prepend the underlying symbol
100  return _underlyingSymbol.Concat(results.Select(x => x.Symbol));
101  }
102 
103  /// <summary>
104  /// Adds the specified security to this universe
105  /// </summary>
106  /// <param name="utcTime">The current utc date time</param>
107  /// <param name="security">The security to be added</param>
108  /// <param name="isInternal">True if internal member</param>
109  /// <returns>True if the security was successfully added,
110  /// false if the security was already in the universe</returns>
111  internal override bool AddMember(DateTime utcTime, Security security, bool isInternal)
112  {
113  // never add members to disposed universes
114  if (DisposeRequested)
115  {
116  return false;
117  }
118 
119  if (Securities.ContainsKey(security.Symbol))
120  {
121  return false;
122  }
123 
124  // method take into account the case, when the option has experienced an adjustment
125  // we update member reference in this case
126  if (Securities.Any(x => x.Value.Security == security))
127  {
128  Member member;
129  Securities.TryRemove(security.Symbol, out member);
130  }
131 
132  return Securities.TryAdd(security.Symbol, new Member(utcTime, security, isInternal));
133  }
134 
135  /// <summary>
136  /// Gets the subscription requests to be added for the specified security
137  /// </summary>
138  /// <param name="security">The security to get subscriptions for</param>
139  /// <param name="currentTimeUtc">The current time in utc. This is the frontier time of the algorithm</param>
140  /// <param name="maximumEndTimeUtc">The max end time</param>
141  /// <param name="subscriptionService">Instance which implements <see cref="ISubscriptionDataConfigService"/> interface</param>
142  /// <returns>All subscriptions required by this security</returns>
143  public override IEnumerable<SubscriptionRequest> GetSubscriptionRequests(Security security, DateTime currentTimeUtc, DateTime maximumEndTimeUtc,
144  ISubscriptionDataConfigService subscriptionService)
145  {
146  if (Option.Symbol.Underlying == security.Symbol)
147  {
148  Option.Underlying = security;
150  }
151  else
152  {
153  // set the underlying security and pricing model from the canonical security
154  var option = (Option)security;
155  option.PriceModel = Option.PriceModel;
156  }
157 
158  return base.GetSubscriptionRequests(security, currentTimeUtc, maximumEndTimeUtc, subscriptionService);
159  }
160  }
161 }