/// <summary> /// Sets the appropriate closing time for each bar, since IB only gives us the opening time. /// </summary> private void GenerateIntradayBarClosingTimes(List <OHLCBar> bars, BarSize frequency) { TimeSpan freqTS = frequency.ToTimeSpan(); for (int i = 0; i < bars.Count; i++) { var bar = bars[i]; if (i == bars.Count - 1) { //if it's the last bar we are basically just guessing the //closing time by adding the duration of the frequency bar.DT = bar.DTOpen.Value + freqTS; } else { //if it's not the last bar, we set the closing time to the //earliest of the open of the next bar and the period of the frequency //e.g. if hourly bar opens at 9:30 and the next bar opens at 10:00 //we set the close at the earliest of 10:00 and 10:30 DateTime openPlusBarSize = bar.DTOpen.Value + freqTS; bar.DT = bars[i + 1].DTOpen.Value < openPlusBarSize ? bars[i + 1].DTOpen.Value : openPlusBarSize; } } }
/// <summary> /// Returns the maximum period length of a historical data request, in seconds, depending on the data frequency. /// </summary> /// <param name="frequency"></param> /// <returns>Maximum allowed length in </returns> public static int MaxRequestLength(QDMS.BarSize frequency) { //The limitations are laid out here: https://www.interactivebrokers.com/en/software/api/apiguide/tables/historical_data_limitations.htm if (frequency <= QDMS.BarSize.OneSecond) { return(1800); } if (frequency <= QDMS.BarSize.FiveSeconds) { return(7200); } if (frequency <= QDMS.BarSize.FifteenSeconds) { return(14400); } if (frequency <= QDMS.BarSize.ThirtySeconds) { return(24 * 3600); } if (frequency <= QDMS.BarSize.OneMinute) { return(2 * 24 * 3600); } if (frequency <= QDMS.BarSize.ThirtyMinutes) { return(7 * 24 * 3600); } if (frequency <= QDMS.BarSize.OneHour) { return(29 * 24 * 3600); } return(365 * 24 * 3600); }
public static QDMSIBClient.BarSize BarSizeConverter(QDMS.BarSize freq) { switch (freq) { case QDMS.BarSize.Tick: throw new Exception("Bar size conversion impossible, TWS does not suppor tick BarSize"); case QDMS.BarSize.OneSecond: return(QDMSIBClient.BarSize.OneSecond); case QDMS.BarSize.FiveSeconds: return(QDMSIBClient.BarSize.FiveSeconds); case QDMS.BarSize.FifteenSeconds: return(QDMSIBClient.BarSize.FifteenSeconds); case QDMS.BarSize.ThirtySeconds: return(QDMSIBClient.BarSize.ThirtySeconds); case QDMS.BarSize.OneMinute: return(QDMSIBClient.BarSize.OneMinute); case QDMS.BarSize.TwoMinutes: return(QDMSIBClient.BarSize.TwoMinutes); case QDMS.BarSize.FiveMinutes: return(QDMSIBClient.BarSize.FiveMinutes); case QDMS.BarSize.FifteenMinutes: return(QDMSIBClient.BarSize.FifteenMinutes); case QDMS.BarSize.ThirtyMinutes: return(QDMSIBClient.BarSize.ThirtyMinutes); case QDMS.BarSize.OneHour: return(QDMSIBClient.BarSize.OneHour); case QDMS.BarSize.OneDay: return(QDMSIBClient.BarSize.OneDay); case QDMS.BarSize.OneWeek: return(QDMSIBClient.BarSize.OneWeek); case QDMS.BarSize.OneMonth: return(QDMSIBClient.BarSize.OneMonth); case QDMS.BarSize.OneQuarter: throw new Exception("Bar size conversion impossible, TWS does not suppor quarter BarSize."); case QDMS.BarSize.OneYear: return(QDMSIBClient.BarSize.OneYear); default: return(QDMSIBClient.BarSize.OneDay); } }
public static string TimespanToDurationString(TimeSpan t, QDMS.BarSize minFreq) { // duration: // This is the time span the request will cover, and is specified using the // format: , i.e., 1 D, where valid units are: S (seconds) D (days) W (weeks) // M (months) Y (years) If no unit is specified, seconds are used. "years" is // currently limited to one. if (minFreq > QDMS.BarSize.OneMonth) { return(Math.Ceiling(Math.Max(1, t.TotalDays / 365)).ToString("0") + " Y"); } if (minFreq >= QDMS.BarSize.OneMonth) { return(Math.Ceiling(Math.Max(1, t.TotalDays / 29)).ToString("0") + " M"); } if (minFreq >= QDMS.BarSize.OneWeek) { return(Math.Ceiling(Math.Max(1, t.TotalDays / 7)).ToString("0") + " W"); } if (minFreq >= QDMS.BarSize.OneDay || t.TotalSeconds > 86400) { if (t.TotalDays > 14) { //This is a ridiculous hack made necessary by the incredibly bad TWS API //For longer periods, if we specify the period as a # of days, the request is rejected! //so instead we do it as the number of weeks and everything is A-OK return(Math.Ceiling(t.TotalDays / 7).ToString("0") + " W"); } else { return(Math.Ceiling(Math.Max(1, t.TotalDays)).ToString("0") + " D"); } } return(Math.Ceiling(t.TotalSeconds).ToString("0") + " S"); }
/// <summary> /// Returns RealTimeDataEventArgs derived from IB's RealTimeBarEventArgs, but not including the symbol /// </summary> /// <param name="e">RealTimeBarEventArgs</param> /// <returns>RealTimeDataEventArgs </returns> public static RealTimeDataEventArgs RealTimeDataEventArgsConverter(RealTimeBarEventArgs e, QDMS.BarSize frequency) { return(new RealTimeDataEventArgs( 0, frequency, e.Time, (decimal)e.Open, (decimal)e.High, (decimal)e.Low, (decimal)e.Close, e.Volume, e.Wap, e.Count, 0)); }