17 using System.Collections.Generic;
19 using Newtonsoft.Json;
32 [ProtoContract(SkipConstructor =
true)]
37 private readonly
object _locker =
new object();
57 :
new List<Symbol>(0);
67 return _currencyConversion;
72 var lastConversionRate = 0m;
73 if (_currencyConversion !=
null)
79 _currencyConversion = value;
80 if (_currencyConversion !=
null)
82 if (lastConversionRate != 0m)
94 private void OnConversionRateUpdated(
object sender, decimal e)
109 public decimal
Amount {
get;
private set; }
123 if (_currencyConversion ==
null)
149 public Cash(
string symbol, decimal amount, decimal conversionRate)
151 if (
string.IsNullOrEmpty(symbol))
156 Symbol = symbol.LazyToUpper();
166 _currencyConversion.
Update();
193 lock (_locker ??
new object())
223 IReadOnlyDictionary<SecurityType, string> marketMap,
226 string accountCurrency,
237 if (
Symbol == accountCurrency)
244 var securitiesToSearch = securities.Select(kvp => kvp.Value)
246 .Where(s => ProvidesConversionRate(s.Type));
249 var markets = securities.Select(x => x.Key)
250 .GroupBy(x => x.SecurityType)
251 .ToDictionary(x => x.Key, y => y.Select(symbol => symbol.ID.Market).ToHashSet());
261 var forexEntries = GetAvailableSymbolPropertiesDatabaseEntries(
SecurityType.Forex, marketMap, markets);
262 var cfdEntries = GetAvailableSymbolPropertiesDatabaseEntries(
SecurityType.Cfd, marketMap, markets);
263 var cryptoEntries = GetAvailableSymbolPropertiesDatabaseEntries(
SecurityType.Crypto, marketMap, markets);
265 var potentialEntries = forexEntries
267 .Concat(cryptoEntries)
270 if (!potentialEntries.Any(x =>
271 Symbol == x.Key.
Symbol.Substring(0, x.Key.Symbol.Length - x.Value.QuoteCurrency.Length) ||
283 if (marketMap.TryGetValue(
SecurityType.Crypto, out var market)
292 var requiredSecurities =
new List<SubscriptionDataConfig>();
294 var potentials = potentialEntries
297 var minimumResolution = subscriptions.
Subscriptions.Select(x => x.Resolution).DefaultIfEmpty(defaultResolution).Min();
299 var makeNewSecurity =
new Func<Symbol, Security>(symbol =>
301 var securityType = symbol.ID.SecurityType;
305 var objectType = type.Item1;
306 var tickType = type.Item2;
312 extendedMarketHours:
false,
313 isInternalFeed:
true,
314 subscriptionDataTypes:
new List<Tuple<Type, TickType>>
315 {
new Tuple<Type, TickType>(objectType, tickType)}).First();
319 addToSymbolCache:
false);
323 securities.
Add(symbol, newSecurity);
324 requiredSecurities.Add(config);
331 securitiesToSearch.ToList(),
335 return requiredSecurities;
356 private static IEnumerable<KeyValuePair<SecurityDatabaseKey, SymbolProperties>> GetAvailableSymbolPropertiesDatabaseEntries(
358 IReadOnlyDictionary<SecurityType, string> marketMap,
359 IReadOnlyDictionary<
SecurityType, HashSet<string>> markets
362 var marketJoin =
new HashSet<string>();
365 if (marketMap.TryGetValue(securityType, out market))
367 marketJoin.Add(market);
369 HashSet<string> existingMarkets;
370 if (markets.TryGetValue(securityType, out existingMarkets))
372 foreach (var existingMarket
in existingMarkets)
374 marketJoin.Add(existingMarket);
379 return marketJoin.SelectMany(market => SymbolPropertiesDatabase.FromDataFolder()
380 .GetSymbolPropertiesList(market, securityType));
383 private static bool ProvidesConversionRate(
SecurityType securityType)
388 private void OnUpdate()
390 Updated?.Invoke(
this, EventArgs.Empty);