17 using System.Collections;
18 using System.Collections.Concurrent;
19 using System.Collections.Generic;
20 using System.Collections.Immutable;
21 using System.Globalization;
25 using System.Net.Http;
26 using System.Reflection;
27 using System.Reflection.Emit;
28 using System.Runtime.CompilerServices;
29 using System.Security.Cryptography;
31 using System.Text.RegularExpressions;
32 using System.Threading;
33 using System.Threading.Tasks;
34 using Newtonsoft.Json;
51 using Timer = System.Timers.Timer;
53 using NodaTime.TimeZones;
61 using Newtonsoft.Json.Linq;
71 private static readonly Dictionary<string, bool> _emptyDirectories =
new ();
72 private static readonly HashSet<string> InvalidSecurityTypes =
new HashSet<string>();
73 private static readonly Regex DateCheck =
new Regex(
@"\d{8}", RegexOptions.Compiled);
74 private static RecyclableMemoryStreamManager MemoryManager =
new RecyclableMemoryStreamManager();
75 private static readonly
int DataUpdatePeriod =
Config.
GetInt(
"downloader-data-update-period", 7);
77 private static readonly Dictionary<IntPtr, PythonActivator> PythonActivators
78 =
new Dictionary<IntPtr, PythonActivator>();
88 private static readonly ZoneLocalMappingResolver _mappingResolver = Resolvers.CreateMappingResolver(Resolvers.ReturnLater, Resolvers.ReturnStartOfIntervalAfter);
114 var jValue = jObject[name];
115 if (jValue !=
null && jValue.Type != JTokenType.Null)
117 result = jValue.Value<T>();
130 var fileName = Path.GetFileName(filepath);
132 return !DateCheck.IsMatch(fileName) && DateTime.Now - TimeSpan.FromDays(DataUpdatePeriod) >
File.GetLastWriteTime(filepath);
143 lock (_emptyDirectories)
145 if(!_emptyDirectories.TryGetValue(directoryPath, out var result))
149 if (Directory.Exists(directoryPath))
153 result = !Directory.EnumerateFileSystemEntries(directoryPath).Any();
155 catch (Exception exception)
161 _emptyDirectories[directoryPath] = result;
164 Log.
Trace($
"Extensions.IsDirectoryEmpty(): directory '{directoryPath}' not found or empty");
184 var type = dataTypes.Single();
185 var baseInstance = type.GetBaseDataInstance();
186 baseInstance.Symbol = symbol;
200 if (result !=
null && dataTypes.Any(dataType => dataType == typeof(
OptionUniverse)))
214 return DeserializeList<string>(jsonArray);
225 if (
string.IsNullOrEmpty(jsonArray))
229 return JsonConvert.DeserializeObject<List<T>>(jsonArray);
233 if (ex is not JsonReaderException && ex is not JsonSerializationException)
238 if (typeof(T) == typeof(
string))
240 return new List<T> { (T)Convert.ChangeType(jsonArray, typeof(T), CultureInfo.InvariantCulture) };
242 return new List<T> { JsonConvert.DeserializeObject<T>(jsonArray) };
252 public static string DownloadData(
this HttpClient client,
string url, Dictionary<string, string> headers =
null)
256 foreach (var kvp
in headers)
258 client.DefaultRequestHeaders.Add(kvp.Key, kvp.Value);
263 using (var response = client.GetAsync(url).Result)
265 using (var content = response.Content)
267 return content.ReadAsStringAsync().Result;
271 catch (WebException ex)
273 Log.
Error(ex, $
"DownloadData(): {Messages.Extensions.DownloadDataFailed(url)}");
283 public static string DownloadData(
this string url, Dictionary<string, string> headers =
null)
285 using var client =
new HttpClient();
286 return client.DownloadData(url, headers);
295 using (var wc =
new HttpClient())
299 return wc.GetByteArrayAsync(url).Result;
303 Log.
Error(ex, $
"DownloadByteArray(): {Messages.Extensions.DownloadDataFailed(url)}");
316 const decimal max = decimal.MaxValue / 100m;
317 if (value >= max)
return decimal.MaxValue;
326 [MethodImpl(MethodImplOptions.AggressiveInlining)]
329 return MemoryManager.GetStream(guid);
343 Serializer.Serialize(stream, ticks);
344 result = stream.ToArray();
360 baseData.ProtobufSerialize(stream);
361 result = stream.ToArray();
377 Serializer.SerializeWithLengthPrefix(stream, baseData as
Tick, PrefixStyle.Base128, 1);
380 Serializer.SerializeWithLengthPrefix(stream, baseData as
QuoteBar, PrefixStyle.Base128, 1);
383 Serializer.SerializeWithLengthPrefix(stream, baseData as
TradeBar, PrefixStyle.Base128, 1);
386 Serializer.SerializeWithLengthPrefix(stream, baseData as
BaseData, PrefixStyle.Base128, 1);
405 if (
string.IsNullOrEmpty(value))
410 if (value.Length == 1)
412 return value.ToLowerInvariant();
414 return char.ToLowerInvariant(value[0]) + value.Substring(1);
427 if (resultPackets.Count > 0)
430 resultPacket = resultPackets[0];
431 for (var i = 1; i < resultPackets.Count; i++)
433 var newerPacket = resultPackets[i];
436 if (newerPacket.Insights !=
null)
441 resultPacket.
Insights =
new List<Insight>();
443 resultPacket.
Insights.AddRange(newerPacket.Insights);
447 if (newerPacket.OrderEvents !=
null)
454 resultPacket.
OrderEvents.AddRange(newerPacket.OrderEvents);
458 if (newerPacket.Orders !=
null)
460 if (resultPacket.
Orders ==
null)
463 resultPacket.
Orders =
new List<Order>();
465 resultPacket.
Orders.AddRange(newerPacket.Orders);
469 resultPacket.
Orders = resultPacket.
Orders.GroupBy(order => order.Id)
470 .Select(ordersGroup => ordersGroup.Last()).ToList();
483 public static void StopSafely(
this Thread thread, TimeSpan timeout, CancellationTokenSource token =
null)
489 if (token !=
null && !token.IsCancellationRequested)
493 Log.
Trace($
"StopSafely(): {Messages.Extensions.WaitingForThreadToStopSafely(thread.Name)}");
495 if (!thread.Join(timeout))
497 Log.
Error($
"StopSafely(): {Messages.Extensions.TimeoutWaitingForThreadToStopSafely(thread.Name)}");
500 catch (Exception exception)
513 public static string GetHash(
this IDictionary<int, Order> orders)
515 var joinedOrders =
string.Join(
518 .OrderBy(pair => pair.Key)
522 var order = pair.Value;
523 order.Price = order.Price.SmartRounding();
524 var limit = order as LimitOrder;
527 limit.LimitPrice = limit.LimitPrice.SmartRounding();
530 if (stopLimit !=
null)
532 stopLimit.
LimitPrice = stopLimit.LimitPrice.SmartRounding();
533 stopLimit.StopPrice = stopLimit.StopPrice.SmartRounding();
536 if (trailingStop !=
null)
538 trailingStop.
TrailingAmount = trailingStop.TrailingAmount.SmartRounding();
541 if (stopMarket !=
null)
543 stopMarket.
StopPrice = stopMarket.StopPrice.SmartRounding();
546 if (limitIfTouched !=
null)
548 limitIfTouched.
LimitPrice = limitIfTouched.LimitPrice.SmartRounding();
549 limitIfTouched.TriggerPrice = limitIfTouched.TriggerPrice.SmartRounding();
551 return JsonConvert.SerializeObject(pair.Value, Formatting.None);
556 return joinedOrders.ToMD5();
567 IEnumerator<DateTime> dates =
null;
573 if (!dates.MoveNext())
582 if (timeUtc >= dates.Current)
584 if (!dates.MoveNext())
589 return dates.Current;
591 catch (InvalidOperationException)
604 return series.
Values.Count == 0;
613 return chart.
Series.Values.All(IsEmpty);
629 var snakeCasedNamed = name.ToSnakeCase();
630 if (snakeCasedNamed != name)
632 method = instance.GetPythonMethodWithChecks(snakeCasedNamed);
639 method = instance.GetAttr(name);
640 var pythonType = method.GetPythonType();
641 var isPythonDefined = pythonType.Repr().Equals(
"<class \'method\'>", StringComparison.Ordinal);
662 var objectType = instance.GetPythonType();
663 if (!objectType.HasAttr(name))
668 var
property = instance.GetAttr(name);
669 var pythonType =
property.GetPythonType();
670 var isPythonDefined = pythonType.Repr().Equals(
"<class \'bool\'>", StringComparison.Ordinal);
691 if (!instance.HasAttr(name))
696 return instance.GetPythonBoolProperty(name);
710 if (!instance.HasAttr(name))
715 return instance.GetPythonMethod(name);
727 public static dynamic
GetMethod(
this PyObject instance,
string name)
729 using var _ = Py.GIL();
730 return instance.GetPythonMethodWithChecks(name.ToSnakeCase()) ?? instance.GetAttr(name);
743 var pyArgCount = PyModule.FromString(Guid.NewGuid().ToString(),
744 "from inspect import signature\n" +
745 "def GetArgCount(method):\n" +
746 " return len(signature(method).parameters)\n"
747 ).GetAttr(
"GetArgCount").Invoke(method);
748 pyArgCount.TryConvert(out argCount);
766 this IEnumerable<IPortfolioTarget> targets,
768 bool targetIsDelta =
false)
775 return targets.Select(x =>
777 var security = algorithm.
Securities[x.Symbol];
782 ExistingQuantity = security.Holdings.Quantity
784 .Aggregate(0m, (d, t) => d + t.Quantity - t.QuantityFilled),
788 .Where(x => x.Security.HasData
789 && x.Security.IsTradable
790 && (targetIsDelta ? Math.Abs(x.TargetQuantity) : Math.Abs(x.TargetQuantity - x.ExistingQuantity))
791 >= x.Security.SymbolProperties.LotSize
795 OrderValue = Math.Abs((targetIsDelta ? x.TargetQuantity : (x.TargetQuantity - x.ExistingQuantity)) * x.Security.Price),
796 IsReducingPosition = x.ExistingQuantity != 0
797 && Math.Abs((targetIsDelta ? (x.TargetQuantity + x.ExistingQuantity) : x.TargetQuantity)) < Math.Abs(x.ExistingQuantity)
799 .OrderByDescending(x => x.IsReducingPosition)
800 .ThenByDescending(x => x.OrderValue)
801 .Select(x => x.PortfolioTarget);
813 if (objectActivator ==
null)
818 var instance = objectActivator.Invoke(
new object[] { type });
843 public static T GetAndDispose<T>(
this PyObject instance)
845 if (instance ==
null)
849 var returnInstance = instance.As<T>();
852 return returnInstance;
862 public static void Move<T>(
this List<T> list,
int oldIndex,
int newIndex)
864 var oItem = list[oldIndex];
865 list.RemoveAt(oldIndex);
866 if (newIndex > oldIndex) newIndex--;
867 list.Insert(newIndex, oItem);
877 var bytes =
new byte[str.Length *
sizeof(char)];
878 Buffer.BlockCopy(str.ToCharArray(), 0, bytes, 0, bytes.Length);
889 using var memoryStream =
new MemoryStream();
890 stream.CopyTo(memoryStream);
891 return memoryStream.ToArray();
900 public static void Clear<T>(
this ConcurrentQueue<T> queue)
903 while (queue.TryDequeue(out item)) {
914 public static string GetString(
this byte[] bytes, Encoding encoding =
null)
916 if (encoding ==
null) encoding = Encoding.ASCII;
918 return encoding.GetString(bytes);
926 public static string ToMD5(
this string str)
928 var builder =
new StringBuilder(32);
929 using (var md5Hash = MD5.Create())
931 var data = md5Hash.ComputeHash(Encoding.UTF8.GetBytes(str));
932 for (var i = 0; i < 16; i++)
934 builder.Append(data[i].ToStringInvariant(
"x2"));
937 return builder.ToString();
947 var hash =
new StringBuilder(64);
948 using (var crypt = SHA256.Create())
950 var crypto = crypt.ComputeHash(Encoding.UTF8.GetBytes(data));
951 for (var i = 0; i < 32; i++)
953 hash.Append(crypto[i].ToStringInvariant(
"x2"));
956 return hash.ToString();
964 var stack =
new Stack<char>(15);
967 var value = data % 36;
969 ? (char)(value +
'0')
970 : (char)(value - 10 +
'A');
975 return new string(stack.ToArray());
985 for (var i = symbol.Length - 1; i > -1; i--)
990 var value = (uint)(c <= 57
994 result += baseValue * value;
1008 if (
string.IsNullOrEmpty(text))
1013 byte[] textBytes = Encoding.UTF8.GetBytes(text);
1014 return Convert.ToBase64String(textBytes);
1024 if (
string.IsNullOrEmpty(base64EncodedText))
1026 return base64EncodedText;
1029 byte[] base64EncodedBytes = Convert.FromBase64String(base64EncodedText);
1030 return Encoding.UTF8.GetString(base64EncodedBytes);
1043 var alreadyUpper =
true;
1044 for (
int i = 0; i < data.Length && alreadyUpper; i++)
1046 alreadyUpper =
char.IsUpper(data[i]);
1048 return alreadyUpper ? data : data.ToUpperInvariant();
1061 var alreadyLower =
true;
1062 for (
int i = 0; i < data.Length && alreadyLower; i++)
1064 alreadyLower =
char.IsLower(data[i]);
1066 return alreadyLower ? data : data.ToLowerInvariant();
1078 public static void AddOrUpdate<K, V>(
this ConcurrentDictionary<K, V> dictionary, K key, V value)
1080 dictionary.AddOrUpdate(key, value, (oldkey, oldvalue) => value);
1092 public static TValue AddOrUpdate<TKey, TValue>(
this ConcurrentDictionary<TKey, Lazy<TValue>> dictionary, TKey key, Func<TKey, TValue> addValueFactory, Func<TKey, TValue, TValue> updateValueFactory)
1094 var result = dictionary.AddOrUpdate(key,
new Lazy<TValue>(() => addValueFactory(key)), (key2, old) =>
new Lazy<TValue>(() => updateValueFactory(key2, old.Value)));
1095 return result.Value;
1108 public static void Add<TKey, TElement, TCollection>(
this IDictionary<TKey, TCollection> dictionary, TKey key, TElement element)
1109 where TCollection : ICollection<TElement>,
new()
1112 if (!dictionary.TryGetValue(key, out list))
1114 list =
new TCollection();
1115 dictionary.Add(key, list);
1129 public static ImmutableDictionary<TKey, ImmutableHashSet<TElement>> Add<TKey, TElement>(
1130 this ImmutableDictionary<TKey, ImmutableHashSet<TElement>> dictionary,
1135 ImmutableHashSet<TElement>
set;
1136 if (!dictionary.TryGetValue(key, out
set))
1138 set = ImmutableHashSet<TElement>.Empty.Add(element);
1139 return dictionary.Add(key,
set);
1142 return dictionary.SetItem(key,
set.Add(element));
1154 public static ImmutableSortedDictionary<TKey, ImmutableHashSet<TElement>> Add<TKey, TElement>(
1155 this ImmutableSortedDictionary<TKey, ImmutableHashSet<TElement>> dictionary,
1160 ImmutableHashSet<TElement>
set;
1161 if (!dictionary.TryGetValue(key, out
set))
1163 set = ImmutableHashSet<TElement>.Empty.Add(element);
1164 return dictionary.Add(key,
set);
1167 return dictionary.SetItem(key,
set.Add(element));
1180 if (!dictionary.TryGetValue(key, out list))
1182 dictionary[key] = list =
new List<Tick>(1);
1195 if (d == 0)
return 0;
1196 var scale = (decimal)Math.Pow(10, Math.Floor(Math.Log10((
double) Math.Abs(d))) + 1);
1197 return scale * Math.Round(d / scale, digits);
1209 return number.ToStringInvariant();
1215 return (number - 5m).ToString(
"#,.##", CultureInfo.InvariantCulture) +
"K";
1218 if (number < 100000)
1220 return (number - 50m).ToString(
"#,.#", CultureInfo.InvariantCulture) +
"K";
1223 if (number < 1000000)
1225 return (number - 500m).ToString(
"#,.", CultureInfo.InvariantCulture) +
"K";
1228 if (number < 10000000)
1230 return (number - 5000m).ToString(
"#,,.##", CultureInfo.InvariantCulture) +
"M";
1233 if (number < 100000000)
1235 return (number - 50000m).ToString(
"#,,.#", CultureInfo.InvariantCulture) +
"M";
1238 if (number < 1000000000)
1240 return (number - 500000m).ToString(
"#,,.", CultureInfo.InvariantCulture) +
"M";
1243 return (number - 5000000m).ToString(
"#,,,.##", CultureInfo.InvariantCulture) +
"B";
1255 public static decimal
DiscretelyRoundBy(
this decimal value, decimal quanta, MidpointRounding mode = MidpointRounding.AwayFromZero)
1265 var multiplicand = Math.Round(value / quanta, mode);
1266 return quanta * multiplicand;
1277 if (value >= decimal.MaxValue / 1000
1278 || value <= decimal.MinValue / 1000
1284 return Math.Truncate(1000 * value) / 1000;
1293 if (!input.HasValue)
1297 return input.Value.SmartRounding();
1306 input = Normalize(input);
1311 return Math.Round(input, 4);
1315 return input.RoundToSignificantDigits(7).Normalize();
1324 [MethodImpl(MethodImplOptions.AggressiveInlining)]
1327 if (input.IsNaNOrInfinity())
1329 throw new ArgumentException(
1332 new NotFiniteNumberException(input)
1336 if (input <= (
double) decimal.MinValue)
return decimal.MinValue;
1337 if (input >= (
double) decimal.MaxValue)
return decimal.MaxValue;
1338 return (decimal) input;
1352 return input / 1.000000000000000000000000000000000m;
1363 return Normalize(input).ToString(CultureInfo.InvariantCulture);
1373 return BitConverter.GetBytes(decimal.GetBits(input)[3])[2];
1387 var decimalPlaces = 0;
1388 var hasDecimals =
false;
1390 var length = str.Length;
1392 while (index < length &&
char.IsWhiteSpace(str[index]))
1397 var isNegative = index < length && str[index] ==
'-';
1403 while (index < length)
1405 var ch = str[index++];
1411 else if (
char.IsWhiteSpace(ch))
1417 value = value * 10 + (ch -
'0');
1422 var lo = (int)value;
1423 var mid = (int)(value >> 32);
1424 return new decimal(lo, mid, 0, isNegative, (
byte)(hasDecimals ? decimalPlaces : 0));
1437 var trimmed = str.Trim();
1438 var value = str.TrimEnd(
'%').ToDecimal();
1439 if (trimmed.EndsWith(
"%"))
1454 return decimal.Parse(str, NumberStyles.AllowExponent | NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture);
1466 for (var i = 0; i < str.Length; i++)
1471 value = value * 10 + (str[i] -
'0');
1485 for (var i = 0; i < str.Length; i++)
1490 value = value * 10 + (str[i] -
'0');
1501 if (baseDataType == typeof(
TradeBar) || baseDataType == typeof(
QuoteBar) || baseDataType == typeof(
Tick))
1506 var method = baseDataType.GetMethod(
"Reader",
1508 if (method !=
null && method.DeclaringType == baseDataType)
1521 public static List<string>
ToCsv(
this string str,
int size = 4)
1524 var csv =
new List<string>(size);
1525 for (
int i = 0; i < str.Length; i++)
1529 if (last != 0) last = last + 1;
1530 csv.Add(str.Substring(last, i - last));
1534 if (last != 0) last = last + 1;
1535 csv.Add(str.Substring(last));
1546 public static List<string>
ToCsvData(
this string str,
int size = 4,
char delimiter =
',')
1548 var csv =
new List<string>(size);
1552 var textDataField =
false;
1554 for (var i = 0; i < str.Length; i++)
1556 var current = str[i];
1559 textDataField = !textDataField;
1561 else if (!textDataField && current == delimiter)
1563 csv.Add(str.Substring(last + 1, (i - last)).Trim(
' ',
','));
1571 csv.Add(str.Substring(last + 1).Trim());
1584 [MethodImpl(MethodImplOptions.AggressiveInlining)]
1585 public static bool TryGetFromCsv(
this string csvLine,
int index, out ReadOnlySpan<char> result)
1587 result = ReadOnlySpan<char>.Empty;
1588 if (
string.IsNullOrEmpty(csvLine) || index < 0)
1593 var span = csvLine.AsSpan();
1594 for (
int i = 0; i < index; i++)
1596 var commaIndex = span.IndexOf(
',');
1597 if (commaIndex == -1)
1601 span = span.Slice(commaIndex + 1);
1604 var nextCommaIndex = span.IndexOf(
',');
1605 if (nextCommaIndex == -1)
1607 nextCommaIndex = span.Length;
1610 result = span.Slice(0, nextCommaIndex);
1621 [MethodImpl(MethodImplOptions.AggressiveInlining)]
1624 value = decimal.Zero;
1625 if (!csvLine.TryGetFromCsv(index, out var csvValue))
1630 return decimal.TryParse(csvValue, NumberStyles.Any, CultureInfo.InvariantCulture, out value);
1639 [MethodImpl(MethodImplOptions.AggressiveInlining)]
1642 csvLine.TryGetDecimalFromCsv(index, out var value);
1650 [MethodImpl(MethodImplOptions.AggressiveInlining)]
1653 return double.IsNaN(value) ||
double.IsInfinity(value);
1660 [MethodImpl(MethodImplOptions.AggressiveInlining)]
1663 return double.IsNaN(value) || Math.Abs(value) <
double.Epsilon;
1672 return new decimal(1, 0, 0,
false, 27);
1681 var ext = str.Substring(Math.Max(0, str.Length - 4));
1682 var allowedExt =
new List<string> {
".zip",
".csv",
".json",
".tsv" };
1683 if (!allowedExt.Contains(ext))
1697 var stream =
new MemoryStream();
1698 var writer =
new StreamWriter(stream);
1701 stream.Position = 0;
1712 public static TimeSpan
Round(
this TimeSpan time, TimeSpan roundingInterval, MidpointRounding roundingType)
1714 if (roundingInterval == TimeSpan.Zero)
1720 return new TimeSpan(
1721 Convert.ToInt64(Math.Round(
1722 time.Ticks / (decimal)roundingInterval.Ticks,
1724 )) * roundingInterval.Ticks
1735 public static TimeSpan
Round(
this TimeSpan time, TimeSpan roundingInterval)
1737 return Round(time, roundingInterval, MidpointRounding.ToEven);
1750 [MethodImpl(MethodImplOptions.AggressiveInlining)]
1751 public static DateTime
RoundDown(
this DateTime dateTime, TimeSpan interval)
1753 if (interval == TimeSpan.Zero)
1759 var amount = dateTime.Ticks % interval.Ticks;
1762 return dateTime.AddTicks(-amount);
1775 [MethodImpl(MethodImplOptions.AggressiveInlining)]
1776 public static DateTime
RoundDownInTimeZone(
this DateTime dateTime, TimeSpan roundingInterval, DateTimeZone sourceTimeZone, DateTimeZone roundingTimeZone)
1778 var dateTimeInRoundingTimeZone = dateTime.ConvertTo(sourceTimeZone, roundingTimeZone);
1779 var roundedDateTimeInRoundingTimeZone = dateTimeInRoundingTimeZone.RoundDown(roundingInterval);
1780 return roundedDateTimeInRoundingTimeZone.ConvertTo(roundingTimeZone, sourceTimeZone);
1795 [MethodImpl(MethodImplOptions.AggressiveInlining)]
1799 if (interval == TimeSpan.Zero)
return dateTime;
1801 var rounded = dateTime.RoundDown(interval);
1802 while (!exchangeHours.
IsOpen(rounded, rounded + interval, extendedMarketHours))
1804 rounded -= interval;
1820 [MethodImpl(MethodImplOptions.AggressiveInlining)]
1824 if (interval == TimeSpan.Zero)
return dateTime;
1826 var dateTimeInRoundingTimeZone = dateTime.ConvertTo(exchangeHours.
TimeZone, roundingTimeZone);
1827 var roundedDateTimeInRoundingTimeZone = dateTimeInRoundingTimeZone.RoundDown(interval);
1828 var rounded = roundedDateTimeInRoundingTimeZone.ConvertTo(roundingTimeZone, exchangeHours.
TimeZone);
1830 while (!exchangeHours.
IsOpen(rounded, rounded + interval, extendedMarketHours))
1837 dateTimeInRoundingTimeZone -= interval;
1838 roundedDateTimeInRoundingTimeZone = dateTimeInRoundingTimeZone.RoundDown(interval);
1839 rounded = roundedDateTimeInRoundingTimeZone.ConvertTo(roundingTimeZone, exchangeHours.
TimeZone);
1867 var time = utcTime.ConvertFromUtc(exchangeHours.TimeZone);
1869 return exchangeHours.
IsOpen(time, extendedMarketHours);
1878 public static DateTime
Round(
this DateTime datetime, TimeSpan roundingInterval)
1880 return new DateTime((datetime - DateTime.MinValue).Round(roundingInterval).Ticks);
1893 public static DateTime
RoundUp(
this DateTime time, TimeSpan interval)
1895 if (interval == TimeSpan.Zero)
1901 return new DateTime(((time.Ticks + interval.Ticks - 1) / interval.Ticks) * interval.Ticks);
1912 [MethodImpl(MethodImplOptions.AggressiveInlining)]
1913 public static DateTime
ConvertTo(
this DateTime time, DateTimeZone from, DateTimeZone to,
bool strict =
false)
1917 return from.AtStrictly(LocalDateTime.FromDateTime(time)).WithZone(to).ToDateTimeUnspecified();
1921 return LocalDateTime.FromDateTime(time)
1922 .InZone(from, _mappingResolver)
1924 .ToDateTimeUnspecified();
1934 public static DateTime
ConvertFromUtc(
this DateTime time, DateTimeZone to,
bool strict =
false)
1946 [MethodImpl(MethodImplOptions.AggressiveInlining)]
1947 public static DateTime
ConvertToUtc(
this DateTime time, DateTimeZone from,
bool strict =
false)
1951 return from.AtStrictly(LocalDateTime.FromDateTime(time)).ToDateTimeUtc();
1955 return LocalDateTime.FromDateTime(time)
1956 .InZone(from, _mappingResolver)
1967 return (date.DayOfWeek != DayOfWeek.Saturday && date.DayOfWeek != DayOfWeek.Sunday);
1974 public static void Reset(
this Timer timer)
1989 if (type.AssemblyQualifiedName == typeName)
1993 if (type.FullName == typeName)
1997 if (type.Name == typeName)
2013 while (type !=
null && type != typeof(
object))
2016 if (type.IsGenericType && possibleSuperType.IsGenericTypeDefinition)
2018 cur = type.GetGenericTypeDefinition();
2024 if (possibleSuperType == cur)
2028 type = type.BaseType;
2041 string name = type.Name;
2042 if (type.IsGenericType)
2044 var genericArguments = type.GetGenericArguments();
2045 var toBeReplaced =
"`" + (genericArguments.Length);
2046 name = name.Replace(toBeReplaced, $
"<{string.Join(",
", genericArguments.Select(x => x.GetBetterTypeName()))}>");
2056 [MethodImpl(MethodImplOptions.AggressiveInlining)]
2063 return TimeSpan.Zero;
2073 throw new ArgumentOutOfRangeException(nameof(resolution));
2087 if (requireExactMatch)
2089 if (TimeSpan.Zero == timeSpan)
return Resolution.Tick;
2118 if (Enum.TryParse(value, ignoreCase, out securityType))
2123 if (InvalidSecurityTypes.Add(value))
2125 Log.
Error($
"Extensions.TryParseSecurityType(): {Messages.Extensions.UnableToParseUnknownSecurityType(value)}");
2138 public static T ConvertTo<T>(
this string value)
2140 return (T) value.ConvertTo(typeof (T));
2149 public static object ConvertTo(
this string value, Type type)
2153 return Enum.Parse(type, value,
true);
2156 if (typeof (IConvertible).IsAssignableFrom(type))
2158 return Convert.ChangeType(value, type, CultureInfo.InvariantCulture);
2162 var parse = type.GetMethod(
"Parse",
new[] {typeof (
string)});
2165 var result = parse.Invoke(
null,
new object[] {value});
2169 return JsonConvert.DeserializeObject(value, type);
2180 public static bool WaitOne(
this WaitHandle waitHandle, CancellationToken cancellationToken)
2182 return waitHandle.WaitOne(Timeout.Infinite, cancellationToken);
2198 public static bool WaitOne(
this WaitHandle waitHandle, TimeSpan timeout, CancellationToken cancellationToken)
2200 return waitHandle.WaitOne((
int) timeout.TotalMilliseconds, cancellationToken);
2217 public static bool WaitOne(
this WaitHandle waitHandle,
int millisecondsTimeout, CancellationToken cancellationToken)
2219 return WaitHandle.WaitAny(
new[] { waitHandle, cancellationToken.WaitHandle }, millisecondsTimeout) == 0;
2229 using (var md5 = MD5.Create())
2231 return md5.ComputeHash(stream);
2242 var regx =
new Regex(
"http(s)?://([\\w+?\\.\\w+])+([a-zA-Z0-9\\~\\!\\@\\#\\$\\%\\^\\&\\*\\(\\)_\\-\\=\\+\\\\\\/\\?\\.\\:\\;\\'\\,]*([a-zA-Z0-9\\?\\#\\=\\/]){1})?", RegexOptions.IgnoreCase);
2243 var matches = regx.Matches(source);
2244 foreach (Match match
in matches)
2246 source = source.Replace(match.Value, $
"<a href=\'{match.Value}\' target=\'blank\'>{match.Value}</a>");
2260 var startIndex = 1 + value.IndexOf(left);
2261 var length = value.IndexOf(right, startIndex) - startIndex;
2264 value = value.Substring(startIndex, length);
2265 startIndex = 1 + value.IndexOf(left);
2266 return value.Substring(startIndex).Trim();
2268 return string.Empty;
2280 if (names.Count == 1) {
return names.Single(); }
2285 var searchName = algorithmTypeName.Contains(
'.', StringComparison.InvariantCulture) ? algorithmTypeName :
"." + algorithmTypeName;
2286 return names.SingleOrDefault(x => x.EndsWith(searchName));
2296 return @
enum.ToString().ToLowerInvariant();
2307 switch (securityType)
2338 switch (securityType)
2358 switch (securityType)
2378 if (!securityType.HasOptions() && !securityType.IsOption())
2383 switch (securityType)
2402 switch (optionStyle.LazyToLower())
2421 switch (optionRight.LazyToLower())
2440 switch (optionRight)
2448 return optionRight.ToString();
2460 switch (optionRight)
2479 switch (optionStyle)
2498 if (
string.IsNullOrEmpty(dataMappingMode))
2502 switch (dataMappingMode.LazyToLower())
2505 case "lasttradingday":
2508 case "firstdaymonth":
2511 case "openinterest":
2514 case "openinterestannual":
2529 switch (securityType)
2538 return "futureoption";
2540 return "indexoption";
2554 return "cryptofuture";
2557 return securityType.ToLower();
2576 return "openinterest";
2579 return tickType.ToLower();
2605 return resolution.ToLower();
2617 var limitPrice = 0m;
2619 var triggerPrice = 0m;
2620 var trailingAmount = 0m;
2621 var trailingAsPercentage =
false;
2636 limitPrice = stopLimitOrder.LimitPrice;
2640 stopPrice = trailingStopOrder.
StopPrice;
2641 trailingAmount = trailingStopOrder.TrailingAmount;
2642 trailingAsPercentage = trailingStopOrder.TrailingAsPercentage;
2647 limitPrice = limitIfTouched.LimitPrice;
2654 limitPrice = order.
Price;
2655 stopPrice = order.
Price;
2665 throw new ArgumentOutOfRangeException();
2676 trailingAsPercentage,
2682 submitOrderRequest.SetOrderId(order.
Id);
2683 var orderTicket =
new OrderTicket(transactionManager, submitOrderRequest);
2684 orderTicket.SetOrder(order);
2694 public static void ProcessUntilEmpty<T>(
this IProducerConsumerCollection<T> collection, Action<T> handler)
2697 while (collection.TryTake(out item))
2715 if (pyObject.HasAttr(
"to_string"))
2717 var pyValue = pyObject.InvokeMethod(
"to_string");
2718 value = Environment.NewLine + pyValue;
2723 value = pyObject.ToString();
2724 if (
string.IsNullOrWhiteSpace(value))
2726 var pythonType = pyObject.GetPythonType();
2727 if (pythonType.GetType() == typeof(PyObject))
2729 value = pythonType.ToString();
2733 var type = pythonType.As<Type>();
2734 value = pyObject.AsManagedObject(type).ToString();
2736 pythonType.Dispose();
2755 public static bool TryConvert<T>(
this PyObject pyObject, out T result,
bool allowPythonDerivative =
false)
2757 result =
default(T);
2758 var type = typeof(T);
2760 if (pyObject ==
null)
2772 if (allowPythonDerivative)
2774 result = (T)pyObject.AsManagedObject(type);
2779 if (typeof(Type).IsAssignableFrom(type))
2781 result = (T)pyObject.AsManagedObject(type);
2783 if(!pyObject.HasAttr(
"__name__"))
2788 var castedResult = (Type)pyObject.AsManagedObject(type);
2789 var pythonName = pyObject.GetAttr(
"__name__").GetAndDispose<
string>();
2790 return pythonName == castedResult.Name;
2794 if (typeof(IEnumerable).IsAssignableFrom(type))
2796 result = (T)pyObject.AsManagedObject(type);
2800 using var pythonType = pyObject.GetPythonType();
2801 var csharpType = pythonType.As<Type>();
2803 if (!type.IsAssignableFrom(csharpType))
2808 result = (T)pyObject.AsManagedObject(type);
2813 if (result is IPythonDerivedType)
2823 if (PythonReferenceComparer.Instance.Equals(PyType.Get(csharpType), pythonType))
2831 var name = (((dynamic)pythonType).__name__ as PyObject).GetAndDispose<string>();
2832 return name == result.GetType().Name;
2851 public static bool TryConvertToDelegate<T>(
this PyObject pyObject, out T result)
2853 var type = typeof(T);
2856 if (TryConvert<T>(pyObject, out result))
2861 if (!typeof(MulticastDelegate).IsAssignableFrom(type))
2866 result =
default(T);
2868 if (pyObject ==
null)
2873 var code =
string.Empty;
2874 var types = type.GetGenericArguments();
2878 var locals =
new PyDict();
2881 for (var i = 0; i < types.Length; i++)
2883 var iString = i.ToStringInvariant();
2884 code += $
",t{iString}";
2885 locals.SetItem($
"t{iString}", types[i].ToPython());
2888 locals.SetItem(
"pyObject", pyObject);
2890 var name = type.FullName.Substring(0, type.FullName.IndexOf(
'`'));
2891 code = $
"import System; delegate = {name}[{code.Substring(1)}](pyObject)";
2893 PythonEngine.Exec(code,
null, locals);
2894 result = (T)locals.GetItem(
"delegate").AsManagedObject(typeof(T));
2920 if (typeToConvertTo ==
null)
2922 typeToConvertTo = pyObject.GetPythonType().AsManagedObject(typeof(Type)) as Type;
2925 return pyObject.AsManagedObject(typeToConvertTo);
2934 public static Func<IEnumerable<T>, IEnumerable<Symbol>> ConvertPythonUniverseFilterFunction<T>(
this PyObject universeFilterFunc) where T :
BaseData
2936 Func<IEnumerable<T>,
object> convertedFunc;
2937 Func<IEnumerable<T>, IEnumerable<Symbol>> filterFunc =
null;
2939 if (universeFilterFunc !=
null && universeFilterFunc.TryConvertToDelegate(out convertedFunc))
2941 filterFunc = convertedFunc.ConvertToUniverseSelectionSymbolDelegate();
2954 public static Func<IEnumerable<T>, IEnumerable<Symbol>> ConvertToUniverseSelectionSymbolDelegate<T>(
this Func<IEnumerable<T>,
object> selector) where T :
BaseData
2956 if (selector ==
null)
2958 return (dataPoints) => dataPoints.Select(x => x.Symbol);
2960 return selector.ConvertSelectionSymbolDelegate();
2970 public static Func<T, IEnumerable<Symbol>> ConvertSelectionSymbolDelegate<T>(
this Func<T, object> selector)
2974 var result = selector(data);
2977 : ((
object[])result).Select(x =>
2979 if (x is
Symbol castedSymbol)
2981 return castedSymbol;
2995 public static Func<T, IEnumerable<string>> ConvertToUniverseSelectionStringDelegate<T>(
this Func<T, object> selector)
2999 var result = selector(data);
3011 public static T ConvertToDelegate<T>(
this PyObject pyObject)
3014 if (pyObject.TryConvertToDelegate(out result))
3031 public static Dictionary<TKey, TValue> ConvertToDictionary<TKey, TValue>(
this PyObject pyObject)
3033 var result =
new List<KeyValuePair<TKey, TValue>>();
3036 var inputType = pyObject.GetPythonType().ToString();
3037 var targetType = nameof(PyDict);
3041 using (var pyDict =
new PyDict(pyObject))
3043 targetType = $
"{typeof(TKey).Name}: {typeof(TValue).Name}";
3045 foreach (PyObject item
in pyDict.Items())
3047 inputType = $
"{item[0].GetPythonType()}: {item[1].GetPythonType()}";
3049 var key = item[0].As<TKey>();
3050 var value = item[1].As<TValue>();
3052 result.Add(
new KeyValuePair<TKey, TValue>(key, value));
3062 return result.ToDictionary();
3074 Exception exception =
null;
3075 if (!PyList.IsListType(pyObject))
3082 result = ConvertToSymbol(pyObject, dispose:
false);
3084 catch (Exception ex)
3092 yield
return result;
3097 using var iterator = pyObject.GetIterator();
3098 foreach (PyObject item
in iterator)
3103 result = ConvertToSymbol(item, dispose:
true);
3105 catch (Exception ex)
3110 yield
return result;
3115 if (exception !=
null)
3117 if (pyObject.TryConvert(out IEnumerable<Symbol> symbols))
3119 foreach (var symbol
in symbols)
3121 yield
return symbol;
3137 public static PyList
ToPyList(
this IEnumerable enumerable)
3141 return enumerable.ToPyListUnSafe();
3153 var pyList =
new PyList();
3154 foreach (var item
in enumerable)
3156 using (var pyObject = item.ToPython())
3158 pyList.Append(pyObject);
3174 if (pyObject.TryConvert(out type))
3176 return value.ToStringInvariant().ConvertTo(type).ToString();
3182 throw new ArgumentException($
"GetEnumString(): {Messages.Extensions.ObjectFromPythonIsNotACSharpType(pyObject.Repr())}");
3195 if (pyObject.TryConvert(out type))
3201 if (!PythonActivators.TryGetValue(pyObject.Handle, out var pythonType))
3207 if (pyObject.ToString().StartsWith(
"<class '", StringComparison.InvariantCulture))
3209 type = CreateType(pyObject);
3214 type = pythonType.Type;
3227 if (pyObject.TryConvert(out type))
3233 if (!PythonActivators.TryGetValue(pyObject.Handle, out pythonType))
3235 var assemblyName = pyObject.GetAssemblyName();
3236 var typeBuilder = AssemblyBuilder
3237 .DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run)
3238 .DefineDynamicModule(
"MainModule")
3240 .DefineType(assemblyName.Name, TypeAttributes.Class | TypeAttributes.Public, type);
3247 PythonActivators.Add(pyObject.Handle, pythonType);
3249 return pythonType.Type;
3261 return new AssemblyName(pyObject.Repr().Split(
'\'')[1]);
3272 public static IEnumerable<List<T>> BatchBy<T>(
this IEnumerable<T> enumerable,
int batchSize)
3274 using (var enumerator = enumerable.GetEnumerator())
3276 List<T> list =
null;
3277 while (enumerator.MoveNext())
3281 list =
new List<T> {enumerator.Current};
3283 else if (list.Count < batchSize)
3285 list.Add(enumerator.Current);
3290 list =
new List<T> {enumerator.Current};
3294 if (list?.Count > 0)
3307 public static TResult SynchronouslyAwaitTaskResult<TResult>(
this Task<TResult> task)
3309 return task.ConfigureAwait(
false).GetAwaiter().GetResult();
3319 task.ConfigureAwait(
false).GetAwaiter().GetResult();
3327 public static T SynchronouslyAwaitTask<T>(
this Task<T> task)
3329 return task.ConfigureAwait(
false).GetAwaiter().GetResult();
3339 return string.Join(
"&", pairs.Select(pair => $
"{pair.Key}={pair.Value}"));
3350 if (s.EndsWith(ending, StringComparison.InvariantCulture))
3352 return s.Substring(0, s.Length - ending.Length);
3368 if (!
string.IsNullOrEmpty(s) && !
string.IsNullOrEmpty(start) && s.StartsWith(start, StringComparison.InvariantCulture))
3370 return s.Substring(start.Length);
3422 public static bool IsCustomDataType<T>(
this Symbol symbol)
3426 && type.Equals(typeof(T).Name, StringComparison.InvariantCultureIgnoreCase);
3442 var expiration = symbol.
ID.
Date;
3443 for (var i = 0; i < offset; i++)
3446 DateTime newExpiration;
3448 var monthOffset = 0;
3452 newExpiration = expiryFunction(expiration.AddMonths(monthOffset)).Date;
3453 }
while (newExpiration <= expiration);
3455 expiration = newExpiration;
3467 if (dataConfig.
Symbol.TryGetLiveSubscriptionSymbol(out var mappedSymbol))
3479 EventHandler newDataAvailableHandler,
3480 Func<SubscriptionDataConfig, bool> isExpired,
3483 subscribedConfig = dataConfig;
3484 if (dataConfig.
Symbol.TryGetLiveSubscriptionSymbol(out var mappedSymbol))
3490 IEnumerator<BaseData> result =
null;
3491 if (!isExpired(subscribedConfig))
3493 result = dataQueueHandler.
Subscribe(subscribedConfig, newDataAvailableHandler);
3497 Log.
Trace($
"SubscribeWithMapping(): skip live subscription for expired asset {subscribedConfig}");
3499 return result ?? Enumerable.Empty<
BaseData>().GetEnumerator();
3510 if(dataProvider ==
null)
3514 var stream = dataProvider.
Fetch(file);
3520 using (var streamReader =
new StreamReader(stream))
3525 line = streamReader.ReadLine();
3531 while (line !=
null);
3545 public static BaseData Scale(
this BaseData data, Func<decimal, decimal, decimal, decimal> factorFunc, decimal volumeFactor, decimal factor, decimal sumOfDividends)
3551 if (tradeBar !=
null)
3553 tradeBar.
Open = factorFunc(tradeBar.Open, factor, sumOfDividends);
3554 tradeBar.High = factorFunc(tradeBar.High, factor, sumOfDividends);
3555 tradeBar.Low = factorFunc(tradeBar.Low, factor, sumOfDividends);
3556 tradeBar.Close = factorFunc(tradeBar.Close, factor, sumOfDividends);
3557 tradeBar.Volume = Math.Round(tradeBar.Volume * volumeFactor);
3564 !securityType.IsOption())
3569 var tick = data as
Tick;
3570 if (tick ==
null || tick.TickType ==
TickType.OpenInterest)
3575 if (tick.TickType ==
TickType.Trade)
3577 tick.
Value = factorFunc(tick.Value, factor, sumOfDividends);
3578 tick.Quantity = Math.Round(tick.Quantity * volumeFactor);
3582 tick.BidPrice = tick.BidPrice != 0 ? factorFunc(tick.BidPrice, factor, sumOfDividends) : 0;
3583 tick.BidSize = Math.Round(tick.BidSize * volumeFactor);
3584 tick.AskPrice = tick.AskPrice != 0 ? factorFunc(tick.AskPrice, factor, sumOfDividends) : 0;
3585 tick.AskSize = Math.Round(tick.AskSize * volumeFactor);
3587 if (tick.BidPrice == 0)
3589 tick.Value = tick.AskPrice;
3592 if (tick.AskPrice == 0)
3594 tick.Value = tick.BidPrice;
3598 tick.Value = (tick.BidPrice + tick.AskPrice) / 2m;
3602 if (quoteBar !=
null)
3604 if (quoteBar.Ask !=
null)
3606 quoteBar.
Ask.
Open = factorFunc(quoteBar.Ask.Open, factor, sumOfDividends);
3607 quoteBar.Ask.High = factorFunc(quoteBar.Ask.High, factor, sumOfDividends);
3608 quoteBar.Ask.Low = factorFunc(quoteBar.Ask.Low, factor, sumOfDividends);
3609 quoteBar.Ask.Close = factorFunc(quoteBar.Ask.Close, factor, sumOfDividends);
3611 if (quoteBar.Bid !=
null)
3613 quoteBar.Bid.Open = factorFunc(quoteBar.Bid.Open, factor, sumOfDividends);
3614 quoteBar.Bid.High = factorFunc(quoteBar.Bid.High, factor, sumOfDividends);
3615 quoteBar.Bid.Low = factorFunc(quoteBar.Bid.Low, factor, sumOfDividends);
3616 quoteBar.Bid.Close = factorFunc(quoteBar.Bid.Close, factor, sumOfDividends);
3618 quoteBar.Value = quoteBar.Close;
3619 quoteBar.LastAskSize = Math.Round(quoteBar.LastAskSize * volumeFactor);
3620 quoteBar.LastBidSize = Math.Round(quoteBar.LastBidSize * volumeFactor);
3629 throw new ArgumentOutOfRangeException();
3644 switch (normalizationMode)
3649 return data?.Scale(TimesFactor, 1 / factor, factor, decimal.Zero);
3651 return data.Scale(TimesFactor, 1 / factor, factor, sumOfDividends);
3654 return data.Scale(TimesFactor, 1, factor, decimal.Zero);
3656 return data.Scale(AdditionFactor, 1, factor, decimal.Zero);
3658 return data.Scale(AdditionFactor, 1, factor, decimal.Zero);
3669 [MethodImpl(MethodImplOptions.AggressiveInlining)]
3670 private static decimal TimesFactor(decimal target, decimal factor, decimal sumOfDividends)
3672 return target * factor + sumOfDividends;
3678 [MethodImpl(MethodImplOptions.AggressiveInlining)]
3679 private static decimal AdditionFactor(decimal target, decimal factor, decimal _)
3681 return target + factor;
3691 var priceScaleFrontier = data.
Time;
3700 priceScaleFrontier = data.
EndTime;
3702 return priceScaleFrontier;
3704 return DateTime.MinValue;
3711 public static IOrderedEnumerable<KeyValuePair<TSource, TKey>> OrderBySafe<TSource, TKey>(
3712 this ConcurrentDictionary<TSource, TKey> source, Func<KeyValuePair<TSource, TKey>, TSource> keySelector
3715 return source.SafeEnumeration().OrderBy(keySelector);
3722 public static IOrderedEnumerable<KeyValuePair<TSource, TKey>> OrderBySafe<TSource, TKey>(
3723 this ConcurrentDictionary<TSource, TKey> source, Func<KeyValuePair<TSource, TKey>, TKey> keySelector
3726 return source.SafeEnumeration().OrderBy(keySelector);
3733 public static IEnumerable<KeyValuePair<TSource, TKey>> SafeEnumeration<TSource, TKey>(
3734 this ConcurrentDictionary<TSource, TKey> source)
3736 foreach (var kvp
in source)
3747 switch (securityType)
3769 if (source ==
null || source.Length == 0)
3774 var hex =
new StringBuilder(source.Length * 2);
3775 foreach (var b
in source)
3777 hex.AppendFormat(CultureInfo.InvariantCulture,
"{0:x2}", b);
3780 return hex.ToString();
3807 var sign = Math.Sign(quantity);
3814 throw new ApplicationException(
3815 $
"The skies are falling and the oceans are rising! Math.Sign({quantity}) returned {sign} :/"
3825 foreach (var security
in securityChanges.AddedSecurities)
3827 security.IsTradable =
true;
3830 algorithm.Securities.Add(security);
3833 var activeSecurities = algorithm.UniverseManager.ActiveSecurities;
3834 foreach (var security
in securityChanges.RemovedSecurities)
3836 if (!activeSecurities.ContainsKey(security.Symbol))
3838 security.IsTradable =
false;
3848 Log.
Error(exception, $
"Extensions.SetRuntimeError(): {Messages.Extensions.RuntimeError(algorithm, context)}");
3864 var result = CreateOptionChain(algorithm, symbol, out var option, universeSettings);
3865 option.SetFilter(filter);
3879 var result = CreateOptionChain(algorithm, symbol, out var option, universeSettings);
3880 option.SetFilter(filter);
3901 option = (
Option)algorithm.
AddSecurity(symbol.
Canonical, settings.Resolution, settings.FillForward, settings.Leverage, settings.ExtendedMarketHours);
3915 var result = CreateFutureChain(algorithm, symbol, out var future, universeSettings);
3916 future.SetFilter(filter);
3929 var result = CreateFutureChain(algorithm, symbol, out var future, universeSettings);
3930 future.SetFilter(filter);
3947 var dataNormalizationMode = settings.GetUniverseNormalizationModeOrDefault(symbol.
SecurityType);
3949 future = (
Future)algorithm.
AddSecurity(symbol.
Canonical, settings.Resolution, settings.FillForward, settings.Leverage, settings.ExtendedMarketHours,
3950 settings.DataMappingMode, dataNormalizationMode, settings.ContractDepthOffset);
3956 private static bool _notifiedUniverseSettingsUsed;
3957 private static readonly HashSet<SecurityType> _supportedSecurityTypes =
new()
3981 Action<IReadOnlyCollection<SecurityType>> onError =
null)
3985 if (!_supportedSecurityTypes.Contains(symbol.
SecurityType))
3988 onError?.Invoke(_supportedSecurityTypes);
3997 if (!_notifiedUniverseSettingsUsed)
4000 _notifiedUniverseSettingsUsed =
true;
4002 var leverageMsg = $
" Leverage = {leverage};";
4005 leverageMsg = $
" Leverage = default;";
4007 algorithm.
Debug($
"Will use UniverseSettings for automatically added securities for open orders and holdings. UniverseSettings:" +
4008 $
" Resolution = {resolution};{leverageMsg} FillForward = {fillForward}; ExtendedHours = {extendedHours}");
4011 Log.
Trace(
"GetOrAddUnrequestedSecurity(): Adding unrequested security: " + symbol.
Value);
4016 security = algorithm.
AddOptionContract(symbol, resolution, fillForward, leverage, extendedHours);
4021 security = algorithm.
AddFutureContract(symbol, resolution, fillForward, leverage, extendedHours);
4042 throw new ArgumentOutOfRangeException(nameof(right), right,
null);
4074 request.DataTimeZone,
4075 request.ExchangeHours.TimeZone,
4076 request.FillForwardResolution.HasValue,
4077 request.IncludeExtendedMarketHours,
4079 request.IsCustomData,
4081 isFilteredSubscription,
4082 request.DataNormalizationMode,
4083 request.DataMappingMode,
4084 request.ContractDepthOffset
4113 var type = data.GetType();
4114 var expectedType = type.IsAssignableTo(config.
Type);
4120 if (!configTypeFilter)
4122 return expectedType;
4131 if (isUniverse && !expectedType)
4163 throw new ArgumentOutOfRangeException(nameof(side), side,
null);
4185 throw new ArgumentOutOfRangeException(nameof(direction), direction,
null);
4195 throw new ArgumentOutOfRangeException(nameof(direction), direction,
null);
4202 throw new ArgumentOutOfRangeException(nameof(side), side,
null);
4213 public static bool ListEquals<T>(
this IReadOnlyList<T> left, IReadOnlyList<T> right)
4215 var count = left.Count;
4216 if (count != right.Count)
4221 for (
int i = 0; i < count; i++)
4223 if (!left[i].
Equals(right[i]))
4239 public static int GetListHashCode<T>(
this IReadOnlyList<T> list)
4244 for (
int i = 0; i < list.Count; i++)
4246 hashCode += (hashCode * 397) ^ list[i].GetHashCode();
4290 return profitLoss > 0;
4293 var option = (
Option)security;
4326 foreach (var value
in values)
4328 if (result.HasValue)
4330 result = GreatestCommonDivisor(result.Value, value);
4338 if (!result.HasValue)
4343 return result.Value;
4349 private static int GreatestCommonDivisor(
int a,
int b)
4367 public static decimal
SafeDivision(
this decimal numerator, decimal denominator, decimal failValue = 0)
4371 return (denominator == 0) ? failValue : (numerator / denominator);
4386 if (symbols.Length != 0)
4422 private static Symbol ConvertToSymbol(PyObject item,
bool dispose)
4424 if (PyString.IsStringType(item))
4433 symbol = dispose ? item.GetAndDispose<Symbol>() : item.As<Symbol>();
4437 throw new ArgumentException(Messages.Extensions.ConvertToSymbolEnumerableFailed(item), e);