/// <summary> /// Gets contracts following a quarterly listing procedure, with a limit of /// how many contracts are listed at once. /// </summary> /// <param name="canonicalFuture">Canonical Futures Symbol</param> /// <param name="time">Contracts to look up that are listed at that time</param> /// <param name="limit">Number of Symbols we get back/are listed at a given time</param> /// <returns>Symbols that are listed at the given time</returns> private static List <Symbol> QuarterlyContracts(Symbol canonicalFuture, DateTime time, int limit) { var contractMonth = new DateTime(time.Year, time.Month, 1); var futureExpiry = DateTime.MinValue; var expiryFunc = FuturesExpiryFunctions.FuturesExpiryFunction(canonicalFuture); // Skip any contracts that have already expired. while (futureExpiry < time) { futureExpiry = FuturesExpiryFunctions.FuturesExpiryFunction(canonicalFuture)(contractMonth); contractMonth = contractMonth.AddMonths(1); } // Negate the last incrementation from the while loop to get the actual contract month of the future. var firstFutureContractMonth = contractMonth.AddMonths(-1); var quarterlyContracts = new List <Symbol>(); // Gets the next closest month from the current month in multiples of 3 var quarterlyContractMonth = (int)Math.Ceiling((double)firstFutureContractMonth.Month / 3) * 3; for (var i = 0; i < limit; i++) { // We're past the expiration frontier due to the while loop above, which means // that any contracts from here on out will be greater than the current time. var currentContractMonth = firstFutureContractMonth.AddMonths(-firstFutureContractMonth.Month + quarterlyContractMonth); var currentFutureExpiry = expiryFunc(currentContractMonth); quarterlyContracts.Add(Symbol.CreateFuture(canonicalFuture.ID.Symbol, canonicalFuture.ID.Market, currentFutureExpiry)); quarterlyContractMonth += 3; } return(quarterlyContracts); }
/// <summary> /// Gets Futures contracts that follow a limited cyclical pattern /// </summary> /// <param name="canonicalFuture">Canonical Futures Symbol</param> /// <param name="time">Contracts to look up that are listed at that time</param> /// <param name="contractMonthForNewListings">Contract month that results in new listings after this contract's expiry</param> /// <param name="futureListingCycles"> /// Cycles that define the number of contracts and the months the contracts are listed on, including /// the limit of how many contracts will be listed. /// </param> /// <returns>Symbols that are listed at the given time</returns> private static List <Symbol> MonthlyContractListings( Symbol canonicalFuture, DateTime time, int contractMonthForNewListings, params FuturesListingCycles[] futureListingCycles) { var listings = new List <Symbol>(); var expiryFunc = FuturesExpiryFunctions.FuturesExpiryFunction(canonicalFuture); var yearDelta = 0; var contractMonthForNewListingCycle = new DateTime(time.Year, contractMonthForNewListings, 1); var contractMonthForNewListingCycleExpiry = expiryFunc(contractMonthForNewListingCycle); if (time <= contractMonthForNewListingCycleExpiry) { // Go back a year if we haven't yet crossed this year's contract renewal expiration date. contractMonthForNewListingCycleExpiry = expiryFunc(contractMonthForNewListingCycle.AddYears(-1)); yearDelta = -1; } foreach (var listingCycle in futureListingCycles) { var year = yearDelta; var count = 0; var initialListings = true; while (count != listingCycle.Limit) { var monthStartIndex = 0; if (initialListings) { // For the initial listing, we want to start counting at some month that might not be the first // index of the collection. The index is discovered here and used as the starting point for listed contracts. monthStartIndex = listingCycle.Cycle.Length - listingCycle.Cycle.Count(c => c > contractMonthForNewListingCycleExpiry.Month); initialListings = false; } for (var m = monthStartIndex; m < listingCycle.Cycle.Length; m++) { // Add the future's expiration to the listings var currentContractMonth = new DateTime(time.Year + year, listingCycle.Cycle[m], 1); var currentFutureExpiry = expiryFunc(currentContractMonth); if (currentFutureExpiry >= time) { listings.Add(Symbol.CreateFuture(canonicalFuture.ID.Symbol, canonicalFuture.ID.Market, currentFutureExpiry)); } if (++count == listingCycle.Limit) { break; } } year++; } } return(listings); }
/// <summary> /// Determine if a given Futures contract is a standard contract. /// </summary> /// <param name="symbol">Future symbol</param> /// <returns>True if symbol expiration matches standard expiration</returns> public static bool IsStandard(Symbol symbol) { var contractExpirationDate = symbol.ID.Date; try { // Use our FutureExpiryFunctions to determine standard contracts dates. var expiryFunction = FuturesExpiryFunctions.FuturesExpiryFunction(symbol); var standardExpirationDate = expiryFunction(contractExpirationDate); // Return true if the dates match return(contractExpirationDate.Date == standardExpirationDate.Date); } catch { Log.Error($"Could not find standard date for {symbol}, will be classified as standard"); return(true); } }
/// <summary> /// Determine if a given Futures contract is a standard contract. /// </summary> /// <param name="symbol">Future symbol</param> /// <returns>True if symbol expiration matches standard expiration</returns> public static bool IsStandard(Symbol symbol) { var contractExpirationDate = symbol.ID.Date.Date; try { // Use our FutureExpiryFunctions to determine standard contracts dates. var expiryFunction = FuturesExpiryFunctions.FuturesExpiryFunction(symbol); var monthsToAdd = FuturesExpiryUtilityFunctions.GetDeltaBetweenContractMonthAndContractExpiry(symbol.ID.Symbol, contractExpirationDate); var contractMonth = contractExpirationDate.AddDays(-(contractExpirationDate.Day - 1)) .AddMonths(monthsToAdd); var standardExpirationDate = expiryFunction(contractMonth); // Return true if the dates match return(contractExpirationDate == standardExpirationDate.Date); } catch { Log.Error($"Could not find standard date for {symbol}, will be classified as standard"); return(true); } }