Lean  $LEAN_TAG$
UniverseExtensions.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.Linq;
18 
20 {
21  /// <summary>
22  /// Provides extension methods for the <see cref="Universe"/> class
23  /// </summary>
24  public static class UniverseExtensions
25  {
26  /// <summary>
27  /// Creates a new universe that logically is the result of wiring the two universes together such that
28  /// the first will produce subscriptions for the second and the second will only select on data that has
29  /// passed the first.
30  ///
31  /// NOTE: The <paramref name="first"/> and <paramref name="second"/> universe instances provided
32  /// to this method should not be manually added to the algorithm.
33  /// </summary>
34  /// <param name="first">The first universe in this 'chain'</param>
35  /// <param name="second">The second universe in this 'chain'</param>
36  /// <param name="configurationPerSymbol">True if each symbol as its own configuration, false otherwise</param>
37  /// <returns>A new universe that can be added to the algorithm that represents invoking the first universe
38  /// and then the second universe using the outputs of the first. </returns>
39  public static Universe ChainedTo(this Universe first, Universe second, bool configurationPerSymbol)
40  {
41  var prefilteredSecond = second.PrefilterUsing(first);
42  return new GetSubscriptionRequestsUniverseDecorator(first, (security, currentTimeUtc, maximumEndTimeUtc) =>
43  {
44  return first.GetSubscriptionRequests(security, currentTimeUtc, maximumEndTimeUtc).Select(request => new SubscriptionRequest(
45  template: request,
46  isUniverseSubscription: true,
47  universe: prefilteredSecond,
48  security: security,
49  configuration: configurationPerSymbol ? new SubscriptionDataConfig(prefilteredSecond.Configuration, symbol: security.Symbol) : prefilteredSecond.Configuration,
50  startTimeUtc: currentTimeUtc - prefilteredSecond.Configuration.Resolution.ToTimeSpan(),
51  endTimeUtc: currentTimeUtc.AddSeconds(-1)
52  ));
53  });
54  }
55 
56  /// <summary>
57  /// Creates a new universe that restricts the universe selection data to symbols that passed the
58  /// first universe's selection critera
59  ///
60  /// NOTE: The <paramref name="second"/> universe instance provided to this method should not be manually
61  /// added to the algorithm. The <paramref name="first"/> should still be manually (assuming no other changes).
62  /// </summary>
63  /// <param name="second">The universe to be filtere</param>
64  /// <param name="first">The universe providing the set of symbols used for filtered</param>
65  /// <returns>A new universe that can be added to the algorithm that represents invoking the second
66  /// using the selections from the first as a filter.</returns>
67  public static Universe PrefilterUsing(this Universe second, Universe first)
68  {
69  return new SelectSymbolsUniverseDecorator(second, (utcTime, data) =>
70  {
71  var clone = (BaseDataCollection)data.Clone();
72  clone.Data = clone.Data.Where(d => first.ContainsMember(d.Symbol)).ToList();
73  return second.SelectSymbols(utcTime, clone);
74  });
75  }
76 
77  /// <summary>
78  /// Creates a universe symbol
79  /// </summary>
80  /// <param name="securityType">The security</param>
81  /// <param name="market">The market</param>
82  /// <param name="ticker">The Universe ticker</param>
83  /// <returns>A symbol for user defined universe of the specified security type and market</returns>
84  public static Symbol CreateSymbol(SecurityType securityType, string market, string ticker)
85  {
86  // TODO looks like we can just replace this for Symbol.Create?
87 
89  switch (securityType)
90  {
91  case SecurityType.Base:
92  sid = SecurityIdentifier.GenerateBase(null, ticker, market);
93  break;
94 
95  case SecurityType.Equity:
97  break;
98 
99  case SecurityType.Option:
100  var underlying = SecurityIdentifier.GenerateEquity(SecurityIdentifier.DefaultDate, ticker, market);
101  sid = SecurityIdentifier.GenerateOption(SecurityIdentifier.DefaultDate, underlying, market, 0, 0, 0);
102  break;
103 
104  case SecurityType.FutureOption:
105  var underlyingFuture = SecurityIdentifier.GenerateFuture(SecurityIdentifier.DefaultDate, ticker, market);
106  sid = SecurityIdentifier.GenerateOption(SecurityIdentifier.DefaultDate, underlyingFuture, market, 0, 0, 0);
107  break;
108 
109  case SecurityType.IndexOption:
110  var underlyingIndex = SecurityIdentifier.GenerateIndex(ticker, market);
111  sid = SecurityIdentifier.GenerateOption(SecurityIdentifier.DefaultDate, underlyingIndex, market, 0, 0, OptionStyle.European);
112  break;
113 
114  case SecurityType.Forex:
115  sid = SecurityIdentifier.GenerateForex(ticker, market);
116  break;
117 
118  case SecurityType.Cfd:
119  sid = SecurityIdentifier.GenerateCfd(ticker, market);
120  break;
121 
122  case SecurityType.Index:
123  sid = SecurityIdentifier.GenerateIndex(ticker, market);
124  break;
125 
126  case SecurityType.Future:
128  break;
129 
130  case SecurityType.Crypto:
131  sid = SecurityIdentifier.GenerateCrypto(ticker, market);
132  break;
133 
134  case SecurityType.CryptoFuture:
136  break;
137 
138  case SecurityType.Commodity:
139  default:
140  throw new NotImplementedException($"The specified security type is not implemented yet: {securityType}");
141  }
142 
143  return new Symbol(sid, ticker);
144  }
145  }
146 }