/// <summary> /// Parses the contents as a FactorFile, if error returns a new empty factor file /// </summary> public static IFactorProvider SafeRead(string permtick, IEnumerable <string> contents, SecurityType securityType) { try { DateTime?minimumDate; contents = contents.Distinct(); if (securityType == SecurityType.Future) { return(new MappingContractFactorProvider(permtick, MappingContractFactorRow.Parse(contents, out minimumDate), minimumDate)); } // FactorFileRow.Parse handles entries with 'inf' and exponential notation and provides the associated minimum tradeable date for these cases // previously these cases were not handled causing an exception and returning an empty factor file return(new CorporateFactorProvider(permtick, CorporateFactorRow.Parse(contents, out minimumDate), minimumDate)); } catch (Exception e) { if (securityType == SecurityType.Future) { return(new MappingContractFactorProvider(permtick, Enumerable.Empty <MappingContractFactorRow>())); } return(new CorporateFactorProvider(permtick, Enumerable.Empty <CorporateFactorRow>())); } }
/// <summary> /// Creates a new split from this factor file row and the one chronologically in front of it /// This split may have a split factor of one if this row doesn't represent a split /// </summary> /// <param name="nextCorporateFactorRow">The next factor file row in time</param> /// <param name="symbol">The symbol to use for the split</param> /// <param name="exchangeHours">Exchange hours used for resolving the previous trading day</param> /// <returns>A new split instance</returns> public Split GetSplit(CorporateFactorRow nextCorporateFactorRow, Symbol symbol, SecurityExchangeHours exchangeHours) { if (nextCorporateFactorRow.SplitFactor == 0m) { throw new InvalidOperationException(Invariant( $"Unable to resolve split for '{symbol.ID}' at {Date:yyyy-MM-dd}. Split factor is zero." )); } // find previous trading day var previousTradingDay = exchangeHours.GetNextTradingDay(Date); return(new Split( symbol, previousTradingDay, ReferencePrice, SplitFactor / nextCorporateFactorRow.SplitFactor, SplitType.SplitOccurred )); }
/// <summary> /// Creates a new dividend from this factor file row and the one chronologically in front of it /// This dividend may have a distribution of zero if this row doesn't represent a dividend /// </summary> /// <param name="nextCorporateFactorRow">The next factor file row in time</param> /// <param name="symbol">The symbol to use for the dividend</param> /// <param name="exchangeHours">Exchange hours used for resolving the previous trading day</param> /// <param name="decimalPlaces">The number of decimal places to round the dividend's distribution to, defaulting to 2</param> /// <returns>A new dividend instance</returns> public Dividend GetDividend(CorporateFactorRow nextCorporateFactorRow, Symbol symbol, SecurityExchangeHours exchangeHours, int decimalPlaces = 2) { if (nextCorporateFactorRow.PriceFactor == 0m) { throw new InvalidOperationException(Invariant( $"Unable to resolve dividend for '{symbol.ID}' at {Date:yyyy-MM-dd}. Price factor is zero." )); } // find previous trading day var previousTradingDay = exchangeHours.GetNextTradingDay(Date); return(Dividend.Create( symbol, previousTradingDay, ReferencePrice, PriceFactor / nextCorporateFactorRow.PriceFactor, decimalPlaces )); }