Example #1
0
        /// <summary>
        /// Reads in the factor file for the specified equity symbol
        /// </summary>
        public static IEnumerable <FactorFileRow> Read(string permtick, string market, out DateTime?factorFileMinimumDate)
        {
            factorFileMinimumDate = null;

            var path  = Path.Combine(Globals.DataFolder, "equity", market, "factor_files", permtick.ToLower() + ".csv");
            var lines = File.ReadAllLines(path).Where(l => !string.IsNullOrWhiteSpace(l));

            var hasInfEntry = false;
            var rows        = new List <FactorFileRow>();

            // parse factor file lines
            foreach (var line in lines)
            {
                if (line.Contains("inf"))
                {
                    hasInfEntry = true;
                    continue;
                }

                var row = Parse(line);

                if (hasInfEntry && rows.Count == 0)
                {
                    // special handling for INF values: set minimum date
                    factorFileMinimumDate = row.Date.AddDays(1);
                    row = new FactorFileRow(row.Date.AddDays(-1), row.PriceFactor, row.SplitFactor);
                }

                rows.Add(row);
            }

            return(rows);
        }
Example #2
0
        /// <summary>
        /// Parses the contents as a FactorFile, if error returns a new empty factor file
        /// </summary>
        public static FactorFile SafeRead(string filename, IEnumerable <string> contents)
        {
            var permtick = Path.GetFileNameWithoutExtension(filename);

            try
            {
                DateTime?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 FactorFile(permtick, FactorFileRow.Parse(contents, out minimumDate), minimumDate));
            }
            catch
            {
                return(new FactorFile(permtick, Enumerable.Empty <FactorFileRow>()));
            }
        }
Example #3
0
        /// <summary>
        /// Gets price and split factors to be applied at the specified date
        /// </summary>
        public FactorFileRow GetScalingFactors(DateTime searchDate)
        {
            var factors = new FactorFileRow(searchDate, 1m, 1m);

            // Iterate backwards to find the most recent factors
            foreach (var splitDate in SortedFactorFileData.Keys.Reverse())
            {
                if (splitDate.Date < searchDate.Date)
                {
                    break;
                }
                factors = SortedFactorFileData[splitDate];
            }

            return(factors);
        }
Example #4
0
        /// <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="futureFactorFileRow">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>
        /// <returns>A new dividend instance</returns>
        public Dividend GetDividend(FactorFileRow futureFactorFileRow, Symbol symbol, SecurityExchangeHours exchangeHours)
        {
            if (futureFactorFileRow.PriceFactor == 0m)
            {
                throw new InvalidOperationException($"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 / futureFactorFileRow.PriceFactor
                       ));
        }
Example #5
0
        /// <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="futureFactorFileRow">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(FactorFileRow futureFactorFileRow, Symbol symbol, SecurityExchangeHours exchangeHours)
        {
            if (futureFactorFileRow.SplitFactor == 0m)
            {
                throw new InvalidOperationException($"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 / futureFactorFileRow.SplitFactor,
                       SplitType.SplitOccurred
                       ));
        }
Example #6
0
        /// <summary>
        /// Parses the lines as factor files rows while properly handling inf entries
        /// </summary>
        /// <param name="lines">The lines from the factor file to be parsed</param>
        /// <param name="factorFileMinimumDate">The minimum date from the factor file</param>
        /// <returns>An enumerable of factor file rows</returns>
        public static List <FactorFileRow> Parse(IEnumerable <string> lines, out DateTime?factorFileMinimumDate)
        {
            var hasInfEntry = false;

            factorFileMinimumDate = null;

            var rows = new List <FactorFileRow>();

            // parse factor file lines
            foreach (var line in lines)
            {
                if (line.Contains("inf"))
                {
                    hasInfEntry = true;
                    continue;
                }

                var row = Parse(line);

                if (hasInfEntry && rows.Count == 0)
                {
                    // special handling for INF values: set minimum date
                    factorFileMinimumDate = row.Date.AddDays(1);
                    row = new FactorFileRow(row.Date.AddDays(-1), row.PriceFactor, row.SplitFactor, row.ReferencePrice);
                }

                // ignore zero factor rows
                if (row.PriceScaleFactor > 0)
                {
                    rows.Add(row);
                }
            }

            if (factorFileMinimumDate == null && rows.Count > 0)
            {
                factorFileMinimumDate = rows.Min(ffr => ffr.Date).AddDays(-1);
            }

            return(rows);
        }
Example #7
0
 /// <summary>
 /// Reads a FactorFile in from the <see cref="Globals.DataFolder"/>.
 /// </summary>
 public static FactorFile Read(string permtick, string market)
 {
     return(new FactorFile(permtick, FactorFileRow.Read(permtick, market)));
 }
Example #8
0
        /// <summary>
        /// Reads a FactorFile in from the <see cref="Globals.DataFolder"/>.
        /// </summary>
        public static FactorFile Read(string permtick, string market)
        {
            DateTime?factorFileMinimumDate;

            return(new FactorFile(permtick, FactorFileRow.Read(permtick, market, out factorFileMinimumDate), factorFileMinimumDate));
        }
Example #9
0
        /// <summary>
        /// Calculates the split factor of a <see cref="Split"/>
        /// </summary>
        /// <param name="split">The next <see cref="Split"/></param>
        /// <param name="previousFactorFileRow">The previous <see cref="FactorFileRow"/> generated</param>
        /// <returns><see cref="FactorFileRow"/>  that represents the split event</returns>
        private FactorFileRow CalculateNextSplitFactor(BaseData split, FactorFileRow previousFactorFileRow)
        {
            var eventDayData = GetDailyDataForDate(split.Time);

            // If you don't have the equity data nothing can be done
            if (eventDayData == null)
                return null;

            TradeBar previousClosingPrice = FindPreviousTradableDayClosingPrice(eventDayData.Time);

            return new FactorFileRow(
                    previousClosingPrice.Time,
                    previousFactorFileRow.PriceFactor,
                    (previousFactorFileRow.SplitFactor * split.Value).RoundToSignificantDigits(6)
                );
        }
Example #10
0
        /// <summary>
        /// Calculates the price factor of a <see cref="Dividend"/>
        /// </summary>
        /// <param name="dividend">The next dividend</param>
        /// <param name="previousFactorFileRow">The previous <see cref="FactorFileRow"/> generated</param>
        /// <returns><see cref="FactorFileRow"/> that represents the dividend event</returns>
        private FactorFileRow CalculateNextDividendFactor(BaseData dividend, FactorFileRow previousFactorFileRow)
        {
            var eventDayData = GetDailyDataForDate(dividend.Time);

            // If you don't have the equity data nothing can be calculated
            if (eventDayData == null)
                return null;

            TradeBar previousClosingPrice = FindPreviousTradableDayClosingPrice(eventDayData.Time);

            var priceFactor = previousFactorFileRow.PriceFactor - (dividend.Value / ((previousClosingPrice.Close) * previousFactorFileRow.SplitFactor));

            return new FactorFileRow(previousClosingPrice.Time, priceFactor.RoundToSignificantDigits(7), previousFactorFileRow.SplitFactor);
        }
Example #11
0
 /// <summary>
 /// Generates the <see cref="FactorFileRow"/> that represents a intraday dividend split.
 /// Applies the dividend first.
 /// </summary>
 /// <param name="intraDayDividendSplit"><see cref="IntraDayDividendSplit"/> instance that holds the intraday dividend and split information</param>
 /// <param name="last">The last <see cref="FactorFileRow"/> generated recursivly</param>
 /// <returns><see cref="FactorFileRow"/> that represents an intraday dividend and split</returns>
 private FactorFileRow CalculateIntradayDividendSplit(IntraDayDividendSplit intraDayDividendSplit, FactorFileRow last)
 {
     var row = CalculateNextDividendFactor(intraDayDividendSplit.Dividend, last);
     return CalculateNextSplitFactor(intraDayDividendSplit.Split, row);
 }