Ejemplo n.º 1
0
        private bool CalcNextBackfillRequest()
        {
            downloadStart = downloadStart.AddMinutes(downloadStep);

            // if contiguous contract is being backfilled
            if (TickerData.SymbolParts.IsContinuous)
            {
                DateTime currExp = IBClientHelper.GetContractExpiryDateTime(downloadContract);

                if (currExp < downloadStart)
                {
                    downloadContract = GetCurrentContract(currExp.AddDays(1));
                    downloadStart    = currExp.AddMinutes(-downloadStep);
                    downloadStart    = IBClientHelper.GetAdjustedStartDate(downloadStart, downloadPeriodicity, GetEarliestDownloadDate(), true);
                }
            }

            // if no more to download
            if (downloadPeriodicity < Periodicity.EndOfDay && downloadStart > DateTime.Now ||
                downloadPeriodicity == Periodicity.EndOfDay && downloadStart.Date >= DateTime.Now.Date)
            {
                if (TickerData.QuoteDataStatus == QuotationStatus.DownloadingIntra)
                {
                    TickerData.QuoteDataStatus = QuotationStatus.DownloadedIntra;
                }
                if (TickerData.QuoteDataStatus == QuotationStatus.DownloadingEod)
                {
                    TickerData.QuoteDataStatus = QuotationStatus.DownloadedEod;
                }

                return(false);
            }

            // set the end of the download period
            downloadEnd = downloadStart.AddMinutes(downloadInterval);

            // indicate that more request is needed
            return(true);
        }
Ejemplo n.º 2
0
        private void mBackfill_Click(object sender, EventArgs e)
        {
            if (firstGetQuotesExCall)                   // db periodicity not known yet
            {
                return;
            }

            if (string.IsNullOrEmpty(currentTicker))    // no selected ticker
            {
                return;
            }

            DateTime refreshStartDate = GetRefreshStartDate(sender);

            refreshStartDate = IBClientHelper.GetAdjustedStartDate(refreshStartDate, Periodicity, DateTime.MinValue, false);

            LogAndMessage.Log(MessageType.Info, currentTicker + ": Manual backfill from " + refreshStartDate.ToShortDateString() + ".");

            StringCollection tickerToBackfill = new StringCollection();

            tickerToBackfill.Add(currentTicker);

            StartBackfills(refreshStartDate, tickerToBackfill);
        }
Ejemplo n.º 3
0
        private void mBackfillAll_Click(object sender, EventArgs e)
        {
            if (firstGetQuotesExCall)                   // db periodicity not known yet
            {
                return;
            }

            if (string.IsNullOrEmpty(currentTicker))    // no selected ticker
            {
                return;
            }

            DateTime refreshStartDate = GetRefreshStartDate(sender);

            refreshStartDate = IBClientHelper.GetAdjustedStartDate(refreshStartDate, Periodicity, DateTime.MinValue, false);

            //
            // collecting all tickers
            //

            int stockCount = 0;
            StringCollection tickersInDatabase = new StringCollection();

            LogAndMessage.Log(MessageType.Info, "Manual backfill of all tickers from " + refreshStartDate.ToShortDateString() + ".");

            try
            {
                Type   abAppType = Type.GetTypeFromProgID("Broker.Application");
                object abApp     = Activator.CreateInstance(abAppType);

                // access AB COM interface to get current ticker
                if (abAppType != null && abApp != null)
                {
                    object abStocks     = abAppType.InvokeMember("Stocks", BindingFlags.GetProperty, null, abApp, null);
                    Type   abStocksType = abStocks.GetType();

                    // get the number of stocks in the db
                    stockCount = (int)abStocksType.InvokeMember("Count", BindingFlags.GetProperty, null, abStocks, null);

                    if (stockCount > 0)
                    {
                        Type abStockType = abStocksType.InvokeMember("Item", BindingFlags.GetProperty, null, abStocks, new object[] { 0 }).GetType();

                        for (int i = 0; i < stockCount; i++)
                        {
                            object abStock = abStocksType.InvokeMember("Item", BindingFlags.GetProperty, null, abStocks, new object[] { i });
                            if (abStock != null)
                            {
                                string ticker = (string)abStockType.InvokeMember("Ticker", BindingFlags.GetProperty, null, abStock, null);
                                if (!tickersInDatabase.Contains(ticker))
                                {
                                    tickersInDatabase.Add(ticker);
                                }
                            }
                        }
                    }
                    else
                    {
                        LogAndMessage.Log(MessageType.Trace, "Manual backfill of all symbols failed. Database has no symbols.");
                    }
                }
                else
                {
                    LogAndMessage.Log(MessageType.Warning, "Manual backfill of all symbols failed. ActiveX interface error.");
                }
            }
            catch (Exception ex)
            {
                LogAndMessage.LogAndQueue(MessageType.Error, "Manual backfill of all symbols failed. Exception: " + ex);
            }

            StartBackfills(refreshStartDate, tickersInDatabase);
        }
Ejemplo n.º 4
0
        private void mBackfillWL_Click(object sender, EventArgs e)
        {
            if (firstGetQuotesExCall)                   // db periodicity not known yet
            {
                return;
            }

            if (string.IsNullOrEmpty(currentTicker))    // no selected ticker
            {
                return;
            }

            DateTime refreshStartDate = GetRefreshStartDate(sender);

            refreshStartDate = IBClientHelper.GetAdjustedStartDate(refreshStartDate, Periodicity, DateTime.MinValue, false);

            WatchlistForm watchlistForm = new WatchlistForm(DatabasePath);

            if (DialogResult.OK != watchlistForm.ShowDialog() || watchlistForm.SelectedWatchlistIndices == null)
            {
                return;
            }

            int[] selectedWatchlistIndices = watchlistForm.SelectedWatchlistIndices;

            watchlistForm.Dispose();

            StringCollection tickersInWatchlists = new StringCollection();

            ulong watchlistBits = 0;

            foreach (int watchlistId in selectedWatchlistIndices)
            {
                watchlistBits |= (ulong)1 << watchlistId;
            }

            LogAndMessage.Log(MessageType.Info, "Manual backfill of watchlists (" + watchlistBits.ToString("0x") + ") from " + refreshStartDate.ToShortDateString() + ".");

            try
            {
                Type   abAppType = Type.GetTypeFromProgID("Broker.Application");
                object abApp     = Activator.CreateInstance(abAppType);

                // access AB COM interface to get current ticker
                if (abAppType != null && abApp != null)
                {
                    object abStocks     = abAppType.InvokeMember("Stocks", BindingFlags.GetProperty, null, abApp, null);
                    Type   abStocksType = abStocks.GetType();

                    // get the number of stocks in the db
                    int stockCount = (int)abStocksType.InvokeMember("Count", BindingFlags.GetProperty, null, abStocks, null);

                    if (stockCount > 0)
                    {
                        Type abStockType = abStocksType.InvokeMember("Item", BindingFlags.GetProperty, null, abStocks, new object[] { 0 }).GetType();

                        for (int i = 0; i < stockCount; i++)
                        {
                            object abStock = abStocksType.InvokeMember("Item", BindingFlags.GetProperty, null, abStocks, new object[] { i });
                            if (abStock != null)
                            {
                                string ticker                = (string)abStockType.InvokeMember("Ticker", BindingFlags.GetProperty, null, abStock, null);
                                uint   watchlistBits1        = (uint)(int)abStockType.InvokeMember("WatchListBits", BindingFlags.GetProperty, null, abStock, null);
                                uint   watchlistBits2        = (uint)(int)abStockType.InvokeMember("WatchListBits2", BindingFlags.GetProperty, null, abStock, null);
                                ulong  watchlistBitsCombined = (watchlistBits2 << 32) + watchlistBits1;

                                if ((watchlistBitsCombined & watchlistBits) != 0)
                                {
                                    if (!tickersInWatchlists.Contains(ticker))
                                    {
                                        tickersInWatchlists.Add(ticker);
                                    }
                                }
                            }
                        }
                    }
                    else
                    {
                        LogAndMessage.Log(MessageType.Trace, "Manual backfill of watchlists failed. Database has no symbols.");
                    }
                }
                else
                {
                    LogAndMessage.Log(MessageType.Warning, "Manual backfill of watchlists failed. ActiveX interface error.");
                }
            }
            catch (Exception ex)
            {
                LogAndMessage.LogAndQueue(MessageType.Error, "Manual backfill of watchlists failed. Exception: " + ex);
            }

            if (tickersInWatchlists.Count == 0)
            {
                LogAndMessage.Log(MessageType.Trace, "Manual backfill of watchlists failed. Selected watchlists have no symbols.");
            }
            else
            {
                StartBackfills(refreshStartDate, tickersInWatchlists);
            }
        }
Ejemplo n.º 5
0
        internal override bool Process(FTController ibController, bool allowNewRequest)
        {
            int requestTimeoutPeriod = 75;

            // if contract of the ticker is still being retrieved or headtimestamp of the ticker is needed (not Offline) AND not yet retrieved
            if (TickerData.ContractStatus <= ContractStatus.WaitForResponse ||
                ((FTDataSource.Periodicity == Periodicity.EndOfDay || FTDataSource.AllowMixedEODIntra) && TickerData.HeadTimestampStatus <= HeadTimestampStatus.WaitForResponse))
            {
                return(allowNewRequest);
            }

            if (TickerData.ContractStatus == ContractStatus.Failed || TickerData.ContractStatus == ContractStatus.Offline ||
                TickerData.HeadTimestampStatus == HeadTimestampStatus.Failed || (TickerData.HeadTimestampStatus == HeadTimestampStatus.Offline && (FTDataSource.Periodicity == Periodicity.EndOfDay || FTDataSource.AllowMixedEODIntra)))
            {
                TickerData.QuoteDataStatus = QuotationStatus.Failed;

                IsFinished = true;
                return(allowNewRequest);
            }

            lock (TickerData)   // request handling
            {
                // if reqHistoricalData is send to IB and we are waiting for answer
                if (WaitingForResponse)
                {
                    // request is not yet timed out...
                    if (RequestTime.AddSeconds(requestTimeoutPeriod) > DateTime.Now)
                    {
                        return(allowNewRequest);
                    }

                    // no response arrived in time, request is timed out...
                    LogAndMessage.LogAndQueue(TickerData, MessageType.Info, "Historical data request has timed out. " + ToString(true, LogAndMessage.VerboseLog));

                    RequestTimeouts++;
                    WaitingForResponse = false;

                    // if there were too many reqHistoricalData timeouts
                    if (RequestTimeouts > 2)
                    {
                        // drop this ticker...
                        TickerData.QuoteDataStatus = QuotationStatus.Failed;

                        IsFinished = true;
                        return(allowNewRequest);
                    }
                }

                // if no new request can be sent (request pacing)
                bool histThrottling = !allowNewRequest || TickerData.QuoteDataStatus > QuotationStatus.New && RequestTime.AddSeconds(6.5) > DateTime.Now;

                // process the ticker depending on its state
                switch (TickerData.QuoteDataStatus)
                {
                case QuotationStatus.Offline:

                    LogAndMessage.Log(MessageType.Error, "Program error. Offline ticker cannot get historical update.");

                    IsFinished = true;
                    return(allowNewRequest);

                // All historical data requests are processed for the ticker
                // (the last CalcNextHistoricalDataRequest call sets this state)
                case QuotationStatus.DownloadedEod:

                    #region Merging and backadjusting downloaded quotes of different contracts/expiry into a simgle QuotationList of the continuous contract

                    if (TickerData.SymbolParts.IsContinuous)
                    {
                        QuotationList mergedQuotes = new QuotationList(FTDataSource.Periodicity);

                        int newQuoteIndex;

                        foreach (ContractDetails cd in TickerData.contractDetailsList)
                        {
                            // if there were no quotes receiced for this contract...
                            if (!TickerData.ContinuousQuotesDictionary.ContainsKey(cd.Contract.LocalSymbol))
                            {
                                continue;
                            }

                            newQuoteIndex = 0;

                            if (mergedQuotes.Count > 0)
                            {
                                int     mergedQuoteIndex    = mergedQuotes.Count - 1;
                                AmiDate mergedQuoteDateTime = mergedQuotes[mergedQuoteIndex].DateTime;

                                // move forward to the first quote not overlqapping with prev contract
                                while (newQuoteIndex < TickerData.ContinuousQuotesDictionary[cd.Contract.LocalSymbol].Count - 1 && TickerData.ContinuousQuotesDictionary[cd.Contract.LocalSymbol][newQuoteIndex].DateTime.Date < mergedQuoteDateTime.Date)
                                {
                                    newQuoteIndex++;
                                }

                                // at this point newQuoteIndex points to a quote of the "same" date as mergedQuoteDateTime (if there are quotes for the same day, if not, then the next day)

                                // if daily database then we look for a day where volume on older contract is greater (switch over day)
                                if (FTDataSource.Periodicity == Periodicity.EndOfDay)
                                {
                                    // find the quote that has a lower volume
                                    while (newQuoteIndex > 0 && mergedQuoteIndex > 0 &&
                                           TickerData.ContinuousQuotesDictionary[cd.Contract.LocalSymbol][newQuoteIndex].DateTime.Date == mergedQuotes[mergedQuoteIndex].DateTime.Date &&        // quotes are of same date
                                           TickerData.ContinuousQuotesDictionary[cd.Contract.LocalSymbol][newQuoteIndex].Volume > mergedQuotes[mergedQuoteIndex].Volume)                         // new contract's volume is higher then old contract's volume
                                    {
                                        newQuoteIndex--;
                                        mergedQuoteIndex--;
                                    }
                                    // at this point newQuoteIndex and lastQuoteDateTime point to quote at which contract is replaced
                                }

                                if (TickerData.ContinuousQuotesDictionary[cd.Contract.LocalSymbol][newQuoteIndex].DateTime.Date != mergedQuotes[mergedQuoteIndex].DateTime.Date)
                                {
                                    LogAndMessage.Log(MessageType.Info, TickerData.ToString(cd.Contract) + ": No overlapping quote found. Used dates to change contracts: " + mergedQuotes[mergedQuoteIndex].DateTime + " and " + TickerData.ContinuousQuotesDictionary[cd.Contract.LocalSymbol][newQuoteIndex].DateTime + ".");
                                }
                                else
                                {
                                    LogAndMessage.Log(MessageType.Info, TickerData.ToString(cd.Contract) + ": Switching to new contract on " + mergedQuotes[mergedQuoteIndex].DateTime + ".");
                                }

                                // get "closing prices" of the contract on the same day
                                float  closeOfNewer = TickerData.ContinuousQuotesDictionary[cd.Contract.LocalSymbol][newQuoteIndex].Price;
                                float  closeOfOlder = mergedQuotes[mergedQuoteIndex].Price;
                                double priceMult    = closeOfNewer / closeOfOlder;

                                // back-adjust prev contracts' prices
                                QuotationList tempList = new QuotationList(FTDataSource.Periodicity);
                                for (int i = 0; i < mergedQuoteIndex; i++)
                                {
                                    Quotation quote = mergedQuotes[i];
                                    quote.Open  = (float)(quote.Open * priceMult);
                                    quote.High  = (float)(quote.High * priceMult);
                                    quote.Low   = (float)(quote.Low * priceMult);
                                    quote.Price = (float)(quote.Price * priceMult);
                                    tempList.Merge(quote);
                                }
                                mergedQuotes.Clear();
                                mergedQuotes = tempList;
                            }

                            // add quotes of newer contract
                            for (; newQuoteIndex < TickerData.ContinuousQuotesDictionary[cd.Contract.LocalSymbol].Count; newQuoteIndex++)
                            {
                                mergedQuotes.Merge(TickerData.ContinuousQuotesDictionary[cd.Contract.LocalSymbol][newQuoteIndex]);
                            }
                        }

                        TickerData.Quotes = mergedQuotes;
                    }

                    #endregion

                    // this is not THROTTLED, but counted in general throttling queue
                    ibController.SendSubscriptionRequest(0, TickerData, false);

                    TickerData.QuoteDataStatus = QuotationStatus.Online;

                    return(allowNewRequest);

                // this should never happen (ticker with online status should not be in the queue...)
                case QuotationStatus.Online:

                    LogAndMessage.LogAndQueue(TickerData, MessageType.Info, "Backfill finished, symbol is ready. ");

                    IsFinished = true;
                    return(allowNewRequest);

                // if any error happend
                case QuotationStatus.Failed:

                    // if intraday download received no data response
                    if (errorCode == 162 && FTDataSource.Periodicity < Periodicity.EndOfDay && FTDataSource.Periodicity > Periodicity.FifteenSeconds)
                    {
                        errorCode = 0;

                        // move forward 4 periods to speed up download/find first valid period with available data
                        CalcNextBackfillRequest();
                        CalcNextBackfillRequest();
                        CalcNextBackfillRequest();
                        LogAndMessage.Log(TickerData, MessageType.Trace, "No data returned, fast forward download period.");

                        // start next download
                        TickerData.QuoteDataStatus = QuotationStatus.DownloadingIntra;

                        return(allowNewRequest);
                    }
                    else
                    {
                        LogAndMessage.LogAndQueue(TickerData, MessageType.Info, "Backfill failed, symbol is offline.");

                        IsFinished = true;
                        return(allowNewRequest);
                    }

                // start historical data refresh
                case QuotationStatus.New:

                    if (histThrottling)
                    {
                        return(false);
                    }

                    // calc download properties
                    downloadPeriodicity = FTDataSource.Periodicity;
                    downloadStep        = IBClientHelper.GetDownloadStep(FTDataSource.Periodicity);
                    downloadInterval    = IBClientHelper.GetDownloadInterval(FTDataSource.Periodicity);
                    downloadStart       = IBClientHelper.GetAdjustedStartDate(TickerData.RefreshStartDate, FTDataSource.Periodicity, GetEarliestDownloadDate(), true);
                    downloadEnd         = downloadStart.AddMinutes(downloadInterval);
                    downloadContract    = GetCurrentContract(downloadStart);

                    // remove quotes already stored
                    TickerData.Quotes.Clear();

                    // set next state
                    if (FTDataSource.Periodicity == Periodicity.EndOfDay)
                    {
                        TickerData.QuoteDataStatus = QuotationStatus.DownloadingEod;
                    }
                    else
                    {
                        TickerData.QuoteDataStatus = QuotationStatus.DownloadingIntra;
                    }

                    // not to wait to send next request
                    RequestTime = DateTime.MinValue;

                    // download historical data
                    SendBackfillRequest(ibController);

                    return(false);

                case QuotationStatus.DownloadingEod:
                case QuotationStatus.DownloadingIntra:

                    if (histThrottling)
                    {
                        return(false);
                    }

                    // if previous request timed out
                    if (RequestTimeouts != 0)
                    {
                        SendBackfillRequest(ibController);
                    }

                    // download historical data
                    else if (CalcNextBackfillRequest())
                    {
                        SendBackfillRequest(ibController);
                    }

                    return(false);

                // last CalcNextHistoricalDataRequest call for intraday bars should have set this state
                case QuotationStatus.DownloadedIntra:

                    // if we need EOD data as well
                    if (FTDataSource.AllowMixedEODIntra)
                    {
                        if (histThrottling)
                        {
                            return(false);
                        }

                        // calc download properties for EOD
                        downloadPeriodicity = Periodicity.EndOfDay;
                        downloadStep        = IBClientHelper.GetDownloadStep(Periodicity.EndOfDay);
                        downloadInterval    = IBClientHelper.GetDownloadInterval(Periodicity.EndOfDay);
                        downloadStart       = IBClientHelper.GetAdjustedStartDate(TickerData.RefreshStartDate, Periodicity.EndOfDay, GetEarliestDownloadDate(), true);
                        downloadEnd         = downloadStart.AddMinutes(downloadInterval);
                        downloadContract    = GetCurrentContract(downloadStart);

                        SendBackfillRequest(ibController);

                        TickerData.QuoteDataStatus = QuotationStatus.DownloadingEod;
                    }
                    else
                    {
                        TickerData.QuoteDataStatus = QuotationStatus.DownloadedEod;
                    }

                    return(false);

                default:

                    LogAndMessage.LogAndQueue(TickerData, MessageType.Info, "Program error in backfill logic.");

                    IsFinished = true;
                    return(true);
                }
            }
        }