Lean  $LEAN_TAG$
SymbolPropertiesDatabaseSymbolMapper.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;
19 using System.Collections.Generic;
20 
22 {
23  /// <summary>
24  /// Provides the mapping between Lean symbols and brokerage symbols using the symbol properties database
25  /// </summary>
27  {
28  private readonly string _market;
29 
30  // map Lean symbols to symbol properties
31  private readonly Dictionary<Symbol, SymbolProperties> _symbolPropertiesMap;
32 
33  // map brokerage symbols to Lean symbols we do it per security type because they could overlap, for example binance futures and spot
34  private readonly Dictionary<SecurityType, Dictionary<string, Symbol>> _symbolMap;
35 
36  /// <summary>
37  /// Creates a new instance of the <see cref="SymbolPropertiesDatabaseSymbolMapper"/> class.
38  /// </summary>
39  /// <param name="market">The Lean market</param>
41  {
42  _market = market;
43 
44  var symbolPropertiesList =
47  .GetSymbolPropertiesList(_market)
48  .Where(x => !string.IsNullOrWhiteSpace(x.Value.MarketTicker))
49  .ToList();
50 
51  _symbolPropertiesMap =
52  symbolPropertiesList
53  .ToDictionary(
54  x => Symbol.Create(x.Key.Symbol, x.Key.SecurityType, x.Key.Market),
55  x => x.Value);
56 
57  _symbolMap = new();
58  foreach (var group in _symbolPropertiesMap.GroupBy(x => x.Key.SecurityType))
59  {
60  _symbolMap[group.Key] = group.ToDictionary(
61  x => x.Value.MarketTicker,
62  x => x.Key);
63  }
64  }
65 
66  /// <summary>
67  /// Converts a Lean symbol instance to a brokerage symbol
68  /// </summary>
69  /// <param name="symbol">A Lean symbol instance</param>
70  /// <returns>The brokerage symbol</returns>
71  public string GetBrokerageSymbol(Symbol symbol)
72  {
73  if (symbol == null || string.IsNullOrWhiteSpace(symbol.Value))
74  {
75  throw new ArgumentException($"Invalid symbol: {(symbol == null ? "null" : symbol.Value)}");
76  }
77 
78  if (symbol.ID.Market != _market)
79  {
80  throw new ArgumentException($"Invalid market: {symbol.ID.Market}");
81  }
82 
83  SymbolProperties symbolProperties;
84  if (!_symbolPropertiesMap.TryGetValue(symbol, out symbolProperties) )
85  {
86  throw new ArgumentException($"Unknown symbol: {symbol.Value}/{symbol.SecurityType}/{symbol.ID.Market}");
87  }
88 
89  if (string.IsNullOrWhiteSpace(symbolProperties.MarketTicker))
90  {
91  throw new ArgumentException($"MarketTicker not found in database for symbol: {symbol.Value}");
92  }
93 
94  return symbolProperties.MarketTicker;
95  }
96 
97  /// <summary>
98  /// Converts a brokerage symbol to a Lean symbol instance
99  /// </summary>
100  /// <param name="brokerageSymbol">The brokerage symbol</param>
101  /// <param name="securityType">The security type</param>
102  /// <param name="market">The market</param>
103  /// <param name="expirationDate">Expiration date of the security(if applicable)</param>
104  /// <param name="strike">The strike of the security (if applicable)</param>
105  /// <param name="optionRight">The option right of the security (if applicable)</param>
106  /// <returns>A new Lean Symbol instance</returns>
107  public Symbol GetLeanSymbol(string brokerageSymbol, SecurityType securityType, string market, DateTime expirationDate = default(DateTime), decimal strike = 0, OptionRight optionRight = OptionRight.Call)
108  {
109  if (string.IsNullOrWhiteSpace(brokerageSymbol))
110  {
111  throw new ArgumentException($"Invalid brokerage symbol: {brokerageSymbol}");
112  }
113 
114  if (market != _market)
115  {
116  throw new ArgumentException($"Invalid market: {market}");
117  }
118 
119  if (!_symbolMap.TryGetValue(securityType, out var symbols))
120  {
121  throw new ArgumentException($"Unknown brokerage security type: {securityType}");
122  }
123 
124  if (!symbols.TryGetValue(brokerageSymbol, out var symbol))
125  {
126  throw new ArgumentException($"Unknown brokerage symbol: {brokerageSymbol}");
127  }
128 
129  return symbol;
130  }
131 
132  /// <summary>
133  /// Checks if the Lean symbol is supported by the brokerage
134  /// </summary>
135  /// <param name="symbol">The Lean symbol</param>
136  /// <returns>True if the brokerage supports the symbol</returns>
137  public bool IsKnownLeanSymbol(Symbol symbol)
138  {
139  return !string.IsNullOrWhiteSpace(symbol?.Value) && _symbolPropertiesMap.ContainsKey(symbol);
140  }
141 
142  /// <summary>
143  /// Returns the security type for a brokerage symbol
144  /// </summary>
145  /// <param name="brokerageSymbol">The brokerage symbol</param>
146  /// <returns>The security type</returns>
147  public SecurityType GetBrokerageSecurityType(string brokerageSymbol)
148  {
149  if (string.IsNullOrWhiteSpace(brokerageSymbol))
150  {
151  throw new ArgumentException($"Invalid brokerage symbol: {brokerageSymbol}");
152  }
153 
154  var result = _symbolMap.Select(kvp =>
155  {
156  kvp.Value.TryGetValue(brokerageSymbol, out var symbol);
157  return symbol;
158  }).Where(symbol => symbol != null).ToList();
159 
160  if (result.Count == 0)
161  {
162  throw new ArgumentException($"Unknown brokerage symbol: {brokerageSymbol}");
163  }
164  if (result.Count > 1)
165  {
166  throw new ArgumentException($"Found multiple brokerage symbols: {string.Join(",", result)}");
167  }
168 
169  return result[0].SecurityType;
170  }
171 
172  /// <summary>
173  /// Checks if the symbol is supported by the brokerage
174  /// </summary>
175  /// <param name="brokerageSymbol">The brokerage symbol</param>
176  /// <returns>True if the brokerage supports the symbol</returns>
177  public bool IsKnownBrokerageSymbol(string brokerageSymbol)
178  {
179  if (string.IsNullOrWhiteSpace(brokerageSymbol))
180  {
181  return false;
182  }
183 
184  return _symbolMap.Any(kvp => kvp.Value.ContainsKey(brokerageSymbol));
185  }
186  }
187 }