17 using System.Collections.Generic;
37 private static Dictionary<string, Func<DateTime, List<Symbol>>> _futuresListingRules =
new Dictionary<string, Func<DateTime, List<Symbol>>>
39 {
"ZB", t => QuarterlyContracts(_zb, t, 3) },
40 {
"ZC", t => MonthlyContractListings(
44 new FuturesListingCycles(
new[] { 3, 5, 9 }, 9),
45 new FuturesListingCycles(
new[] { 7, 12 }, 8)) },
46 {
"ZN", t => QuarterlyContracts(_zt, t, 3) },
47 {
"ZS", t => MonthlyContractListings(
51 new FuturesListingCycles(
new[] { 1, 3, 5, 8, 9 }, 15),
52 new FuturesListingCycles(
new[] { 7, 11 }, 8)) },
53 {
"ZT", t => QuarterlyContracts(_zt, t, 3) },
54 {
"ZW", t => MonthlyContractListings(
58 new FuturesListingCycles(
new[] { 3, 5, 7, 9, 12 }, 15)) }
69 if (!_futuresListingRules.ContainsKey(futureTicker))
76 return _futuresListingRules[futureTicker](time);
87 private static List<Symbol> QuarterlyContracts(
Symbol canonicalFuture, DateTime time,
int limit)
89 var contractMonth =
new DateTime(time.Year, time.Month, 1);
90 var futureExpiry = DateTime.MinValue;
94 while (futureExpiry < time)
97 contractMonth = contractMonth.AddMonths(1);
101 var firstFutureContractMonth = contractMonth.AddMonths(-1);
103 var quarterlyContracts =
new List<Symbol>();
105 var quarterlyContractMonth = (int)Math.Ceiling((
double)firstFutureContractMonth.Month / 3) * 3;
107 for (var i = 0; i < limit; i++)
111 var currentContractMonth = firstFutureContractMonth.AddMonths(-firstFutureContractMonth.Month + quarterlyContractMonth);
112 var currentFutureExpiry = expiryFunc(currentContractMonth);
115 quarterlyContractMonth += 3;
118 return quarterlyContracts;
132 private static List<Symbol> MonthlyContractListings(
133 Symbol canonicalFuture,
135 int contractMonthForNewListings,
136 params FuturesListingCycles[] futureListingCycles)
138 var listings =
new List<Symbol>();
139 var expiryFunc = FuturesExpiryFunctions.FuturesExpiryFunction(canonicalFuture);
142 var contractMonthForNewListingCycle =
new DateTime(time.Year, contractMonthForNewListings, 1);
143 var contractMonthForNewListingCycleExpiry = expiryFunc(contractMonthForNewListingCycle);
145 if (time <= contractMonthForNewListingCycleExpiry)
148 contractMonthForNewListingCycleExpiry = expiryFunc(contractMonthForNewListingCycle.AddYears(-1));
152 foreach (var listingCycle
in futureListingCycles)
154 var year = yearDelta;
156 var initialListings =
true;
158 while (count != listingCycle.Limit)
160 var monthStartIndex = 0;
165 monthStartIndex = listingCycle.Cycle.Length - listingCycle.Cycle.Count(c => c > contractMonthForNewListingCycleExpiry.Month);
166 initialListings =
false;
169 for (var m = monthStartIndex; m < listingCycle.Cycle.Length; m++)
172 var currentContractMonth =
new DateTime(time.Year + year, listingCycle.Cycle[m], 1);
173 var currentFutureExpiry = expiryFunc(currentContractMonth);
174 if (currentFutureExpiry >= time)
176 listings.Add(Symbol.CreateFuture(canonicalFuture.ID.Symbol, canonicalFuture.ID.Market, currentFutureExpiry));
179 if (++count == listingCycle.Limit)
204 private class FuturesListingCycles
209 public int[] Cycle {
get; }
214 public int Limit {
get; }
222 public FuturesListingCycles(
int[] cycle,
int limit)