17 using System.Collections.Generic;
47 private static readonly Dictionary<string, Func<DateTime, DateTime?, DateTime?>> _underlyingFuturesOptionsRules =
new Dictionary<string, Func<DateTime, DateTime?, DateTime?>>
58 {
"HG", (d, _) => ContractMonthYearStartThreeMonthsThenEvenOddMonthsSkipRule(d,
true) },
59 {
"SI", (d, _) => ContractMonthYearStartThreeMonthsThenEvenOddMonthsSkipRule(d,
true) },
60 {
"GC", (d, _) => ContractMonthEvenOddMonth(d,
false) }
68 private static readonly IReadOnlyDictionary<string, int> _futuresOptionsExpiryDelta =
new Dictionary<string, int>
97 var contractMonth = GetFutureContractMonthNoRulesApplied(canonicalFuture, futureOptionExpiration);
99 if (_underlyingFuturesOptionsRules.ContainsKey(futureTicker))
102 var newFutureContractMonth = _underlyingFuturesOptionsRules[futureTicker](contractMonth, date);
103 if (newFutureContractMonth ==
null)
111 contractMonth = newFutureContractMonth.Value;
126 private static DateTime? ContractMonthSerialLookupRule(
Symbol canonicalFutureSymbol, DateTime futureOptionContractMonth, DateTime lookupDate)
129 if (futureChain ==
null)
135 foreach (var future
in futureChain.OrderBy(s => s.ID.Date))
140 var futureContractMonth = future.ID.Date.Date
141 .AddDays(-future.ID.Date.Day + 1)
145 if (futureContractMonth < futureOptionContractMonth)
150 return futureContractMonth;
164 private static DateTime ContractMonthEvenOddMonth(DateTime futureOptionContractMonth,
bool oddMonths)
166 var monthEven = futureOptionContractMonth.Month % 2 == 0;
167 if (oddMonths && monthEven)
169 return futureOptionContractMonth.AddMonths(1);
171 if (!oddMonths && !monthEven)
173 return futureOptionContractMonth.AddMonths(1);
176 return futureOptionContractMonth;
185 private static DateTime ContractMonthYearStartThreeMonthsThenEvenOddMonthsSkipRule(DateTime futureOptionContractMonth,
bool oddMonths)
187 if (futureOptionContractMonth.Month <= 3)
189 return new DateTime(futureOptionContractMonth.Year, 3, 1);
192 return ContractMonthEvenOddMonth(futureOptionContractMonth, oddMonths);
202 private static DateTime GetFutureContractMonthNoRulesApplied(Symbol canonicalFutureSymbol, DateTime futureOptionExpirationDate)
204 var baseOptionExpiryMonthDate =
new DateTime(futureOptionExpirationDate.Year, futureOptionExpirationDate.Month, 1);
205 if (!_futuresOptionsExpiryDelta.ContainsKey(canonicalFutureSymbol.ID.Symbol))
213 return baseOptionExpiryMonthDate.AddMonths(futuresDelta);
216 return baseOptionExpiryMonthDate.AddMonths(_futuresOptionsExpiryDelta[canonicalFutureSymbol.ID.Symbol]);