17 using System.Collections.Generic;
38 private static Dictionary<string, Func<DateTime, List<Symbol>>> _futuresListingRules =
new Dictionary<string, Func<DateTime, List<Symbol>>>
40 {
"ZB", t => QuarterlyContracts(_zb, t, 3) },
41 {
"ZC", t => MonthlyContractListings(
45 new FuturesListingCycles(
new[] { 3, 5, 9 }, 9),
46 new FuturesListingCycles(
new[] { 7, 12 }, 8)) },
47 {
"ZN", t => QuarterlyContracts(_zt, t, 3) },
48 {
"ZS", t => MonthlyContractListings(
52 new FuturesListingCycles(
new[] { 1, 3, 5, 8, 9 }, 15),
53 new FuturesListingCycles(
new[] { 7, 11 }, 8)) },
54 {
"ZT", t => QuarterlyContracts(_zt, t, 3) },
55 {
"ZW", t => MonthlyContractListings(
59 new FuturesListingCycles(
new[] { 3, 5, 7, 9, 12 }, 15)) }
70 if (!_futuresListingRules.ContainsKey(futureTicker))
77 return _futuresListingRules[futureTicker](time);
88 private static List<Symbol> QuarterlyContracts(
Symbol canonicalFuture, DateTime time,
int limit)
90 var contractMonth =
new DateTime(time.Year, time.Month, 1);
91 var futureExpiry = DateTime.MinValue;
95 while (futureExpiry < time)
98 contractMonth = contractMonth.AddMonths(1);
102 var firstFutureContractMonth = contractMonth.AddMonths(-1);
104 var quarterlyContracts =
new List<Symbol>();
106 var quarterlyContractMonth = (int)Math.Ceiling((
double)firstFutureContractMonth.Month / 3) * 3;
108 for (var i = 0; i < limit; i++)
112 var currentContractMonth = firstFutureContractMonth.AddMonths(-firstFutureContractMonth.Month + quarterlyContractMonth);
113 var currentFutureExpiry = expiryFunc(currentContractMonth);
116 quarterlyContractMonth += 3;
119 return quarterlyContracts;
133 private static List<Symbol> MonthlyContractListings(
134 Symbol canonicalFuture,
136 int contractMonthForNewListings,
137 params FuturesListingCycles[] futureListingCycles)
139 var listings =
new List<Symbol>();
140 var expiryFunc = FuturesExpiryFunctions.FuturesExpiryFunction(canonicalFuture);
143 var contractMonthForNewListingCycle =
new DateTime(time.Year, contractMonthForNewListings, 1);
144 var contractMonthForNewListingCycleExpiry = expiryFunc(contractMonthForNewListingCycle);
146 if (time <= contractMonthForNewListingCycleExpiry)
149 contractMonthForNewListingCycleExpiry = expiryFunc(contractMonthForNewListingCycle.AddYears(-1));
153 foreach (var listingCycle
in futureListingCycles)
155 var year = yearDelta;
157 var initialListings =
true;
159 while (count != listingCycle.Limit)
161 var monthStartIndex = 0;
166 monthStartIndex = listingCycle.Cycle.Length - listingCycle.Cycle.Count(c => c > contractMonthForNewListingCycleExpiry.Month);
167 initialListings =
false;
170 for (var m = monthStartIndex; m < listingCycle.Cycle.Length; m++)
173 var currentContractMonth =
new DateTime(time.Year + year, listingCycle.Cycle[m], 1);
174 var currentFutureExpiry = expiryFunc(currentContractMonth);
175 if (currentFutureExpiry >= time)
177 listings.Add(Symbol.CreateFuture(canonicalFuture.ID.Symbol, canonicalFuture.ID.Market, currentFutureExpiry));
180 if (++count == listingCycle.Limit)
205 private class FuturesListingCycles
210 public int[] Cycle {
get; }
215 public int Limit {
get; }
223 public FuturesListingCycles(
int[] cycle,
int limit)