Esempio n. 1
0
        /// <summary>
        ///     Process a FrontContractRequest
        ///     CFs with a time-based switchover are calculated on the spot
        ///     CFs with other types of switchover require data, so we send off the appropriate data requests here
        /// </summary>
        private void ProcessFrontContractRequest(FrontContractRequest request)
        {
            _logger.Info($"Processing front contract request for symbol: {request.Instrument.Symbol} at: {(request.Date.HasValue ? request.Date.ToString() : "Now")}");

            if (request.Instrument.ContinuousFuture.RolloverType == ContinuousFuturesRolloverType.Time)
            {
                ProcessTimeBasedFrontContractRequest(request);
            }
            else //otherwise, we have to actually look at the historical data to figure out which contract is selected
            {
                ProcessDataBasedFrontContractRequest(request);
            }
        }
Esempio n. 2
0
        /// <summary>
        /// Finds the currently active futures contract for a continuous futures instrument.
        /// The contract is returned asynchronously through the FoundFrontContract event.
        /// </summary>
        /// <returns>Returns an ID uniquely identifying this request.</returns>
        public int RequestFrontContract(Instrument cfInstrument, DateTime?date = null)
        {
            if (!cfInstrument.IsContinuousFuture)
            {
                throw new Exception("Not a continuous future instrument.");
            }

            _lastFrontDontractRequestID++;
            var req = new FrontContractRequest
            {
                ID         = _lastFrontDontractRequestID,
                Instrument = cfInstrument,
                Date       = date
            };

            ProcessFrontContractRequest(req);

            return(_lastFrontDontractRequestID);
        }
Esempio n. 3
0
        /// <summary>
        ///     Finds the currently active futures contract for a continuous futures instrument.
        ///     The contract is returned asynchronously through the FoundFrontContract event.
        /// </summary>
        /// <returns>Returns an ID uniquely identifying this request.</returns>
        public int RequestFrontContract(Instrument cfInstrument, DateTime?date = null)
        {
            if (!cfInstrument.IsContinuousFuture)
            {
                throw new Exception("Not a continuous future instrument.");
            }

            var id = Interlocked.Increment(ref _lastFrontDontractRequestID);

            var req = new FrontContractRequest
            {
                ID         = id,
                Instrument = cfInstrument,
                Date       = date
            };

            ProcessFrontContractRequest(req);

            return(id);
        }
Esempio n. 4
0
        /// <summary>
        /// Finds the front contract for continuous futures with time-based roll.
        /// </summary>
        private void ProcessTimeBasedFrontContractRequest(FrontContractRequest request)
        {
            DateTime currentDate = request.Date ?? DateTime.Now;
            var      cf          = request.Instrument.ContinuousFuture;

            //if the roll-over is time based, we can find the appropriate contract programmatically
            DateTime selectedDate = currentDate;

            while (!cf.MonthIsUsed(selectedDate.Month))
            {
                selectedDate = selectedDate.AddMonths(1);
            }

            DateTime currentMonthsExpirationDate = cf.UnderlyingSymbol.ExpirationDate(selectedDate.Year, selectedDate.Month);
            DateTime switchOverDate = currentMonthsExpirationDate;

            Calendar calendar = MyUtils.GetCalendarFromCountryCode("US");

            //the front contract
            //find the switchover date
            int daysBack = cf.RolloverDays;

            while (daysBack > 0)
            {
                switchOverDate = switchOverDate.AddDays(-1);
                if (calendar.isBusinessDay(switchOverDate))
                {
                    daysBack--;
                }
            }

            //this month's contract has already been switched to the next one
            int monthsLeft = 1;
            int count      = 0;

            if (currentDate >= switchOverDate)
            {
                while (monthsLeft > 0)
                {
                    count++;
                    if (cf.MonthIsUsed(selectedDate.AddMonths(count).Month))
                    {
                        monthsLeft--;
                    }
                }
                selectedDate = selectedDate.AddMonths(count);
            }

            //we found the "front" month, no go back the required number of months
            //while skipping unused months
            monthsLeft = cf.Month - 1;
            count      = 0;
            while (monthsLeft > 0)
            {
                if (cf.MonthIsUsed(selectedDate.AddMonths(count).Month))
                {
                    monthsLeft--;
                }
                count++;
            }
            selectedDate = selectedDate.AddMonths(count);

            string tradingClass = request.Instrument.TradingClass;

            //we got the month we want! find the contract
            Instrument contract = _instrumentRepo.FindInstruments(x => x.Expiration.HasValue &&
                                                                  x.Expiration.Value.Month == selectedDate.Month &&
                                                                  x.Expiration.Value.Year == selectedDate.Year &&
                                                                  x.UnderlyingSymbol == cf.UnderlyingSymbol.Symbol &&
                                                                  (string.IsNullOrEmpty(tradingClass) || x.TradingClass == tradingClass)).Result.FirstOrDefault();

            var timer = new Timer(50)
            {
                AutoReset = false
            };

            timer.Elapsed += (sender, e) =>
            {
                lock (_frontContractReturnLock)
                {
                    RaiseEvent(FoundFrontContract, this, new FoundFrontContractEventArgs(request.ID, contract, currentDate));
                }
            };
            timer.Start();
        }
Esempio n. 5
0
        /// <summary>
        /// Finds the front contract for continuous futures with non-time-based roll.
        /// </summary>
        private void ProcessDataBasedFrontContractRequest(FrontContractRequest request)
        {
            DateTime currentDate = request.Date ?? DateTime.Now;

            //this is a tough one, because it needs to be asynchronous (historical
            //data can take a long time to download).
            var r = new Random();

            //we use GetRequiredRequests to get the historical requests we need to make
            var tmpReq = new HistoricalDataRequest
            {
                Instrument   = request.Instrument,
                StartingDate = currentDate.AddDays(-1),
                EndingDate   = currentDate,
                Frequency    = BarSize.OneDay
            };

            //give the request a unique id
            lock (_requestsLock)
            {
                int id;
                do
                {
                    id = r.Next();
                } while (_requests.ContainsKey(id));
                tmpReq.AssignedID = id;
                _requests.Add(tmpReq.AssignedID, tmpReq);
            }

            var reqs = GetRequiredRequests(tmpReq);

            //make sure the request is fulfillable with the available contracts, otherwise return empty-handed
            if (reqs.Count == 0 || reqs.Count(x => x.Instrument.Expiration.HasValue && x.Instrument.Expiration.Value >= request.Date) == 0)
            {
                lock (_frontContractReturnLock)
                {
                    RaiseEvent(FoundFrontContract, this, new FoundFrontContractEventArgs(request.ID, null, currentDate));
                }
                lock (_requestsLock)
                {
                    _requests.Remove(tmpReq.AssignedID);
                }
                return;
            }

            // add it to the collection of requests so we can access it later
            _requestTypes.Add(tmpReq.AssignedID, false);

            //add it to the front contract requests map
            _frontContractRequestMap.Add(tmpReq.AssignedID, request);

            //finally send out a request for all the data...when it arrives,
            //we process it and return the required front future
            foreach (HistoricalDataRequest req in reqs)
            {
                lock (_dataUsesLock)
                {
                    var kvp = new KeyValuePair <int, BarSize>(req.Instrument.ID.Value, req.Frequency);
                    if (_dataUsesPending.ContainsKey(kvp))
                    {
                        _dataUsesPending[kvp]++;
                    }
                    else
                    {
                        _dataUsesPending.Add(kvp, 1);
                    }
                }
                int requestID = _client.RequestHistoricalData(req);
                _histReqIDMap.Add(requestID, tmpReq.AssignedID);
            }
        }
Esempio n. 6
0
        /// <summary>
        /// Historical data has arrived.
        /// Add it to our data store, then check if all requests have been
        /// fulfilled for a particular continuous futures request. If they
        /// have, go do the calculations.
        /// </summary>
        private void _client_HistoricalDataReceived(object sender, HistoricalDataEventArgs e)
        {
            if (e.Request.Instrument.ID == null)
            {
                return;
            }
            int id    = e.Request.Instrument.ID.Value;
            var kvpID = new KeyValuePair <int, BarSize>(id, e.Request.Frequency);

            lock (_data)
            {
                if (_data.ContainsKey(kvpID))
                {
                    //We already have data on this instrument ID/Frequency combo.
                    //Add the arrived data, then discard any doubles, then order.
                    _data[kvpID].AddRange(e.Data);
                    _data[kvpID] = _data[kvpID].Distinct((x, y) => x.DT == y.DT).ToList();
                    _data[kvpID] = _data[kvpID].OrderBy(x => x.DT).ToList();
                }
                else
                {
                    //We have nothing on this instrument ID/Frequency combo.
                    //Just add a new entry in the dictionary.
                    _data.Add(kvpID, e.Data);
                }
            }

            //Here we check if all necessary requests have arrived. If they have, do some work.
            lock (_reqCountLock)
            {
                //get the request id of the continuous futures request that caused this contract request
                int cfReqID = _histReqIDMap[e.Request.RequestID];
                _histReqIDMap.Remove(e.Request.RequestID);
                _requestCounts[cfReqID]--;

                if (_requestCounts[cfReqID] == 0)
                {
                    //we have received all the data we asked for
                    _requestCounts.Remove(e.Request.RequestID);
                    HistoricalDataRequest req;
                    lock (_requestsLock)
                    {
                        req = _requests[cfReqID];
                        _requests.Remove(cfReqID);
                    }

                    if (_requestTypes[cfReqID])
                    {
                        //This request originates from a CF data request
                        //so now we want to generate the continuous prices
                        GetContFutData(req);
                    }
                    else
                    {
                        //This request originates from a front contract request
                        Instrument           frontContract = GetContFutData(req, false);
                        FrontContractRequest originalReq   = _frontContractRequestMap[cfReqID];
                        lock (_frontContractReturnLock)
                        {
                            RaiseEvent(FoundFrontContract, this, new FoundFrontContractEventArgs(originalReq.ID, frontContract, originalReq.Date == null ? DateTime.Now : originalReq.Date.Value));
                        }
                    }

                    _requestTypes.Remove(e.Request.AssignedID);
                }
            }
        }