Historical Bar Data
Requesting Historical Bar Data
Historical data is obtained from the the TWS via the LYNXApi.EClient.reqHistoricalData function. Every request needs:
- tickerId, A unique identifier which will serve to identify the incoming data.
- contract, The LYNXApi.Contract you are interested in.
- endDateTime, The request's end date and time (the empty string indicates current present moment).
- durationString, The amount of time (or Valid Duration String units) to go back from the request's given end date and time.
- barSizeSetting, The data's granularity or Valid Bar Sizes
- whatToShow, The type of data to retrieve. See Historical Data Types
- useRTH, Whether (1) or not (0) to retrieve data generated only within Regular Trading Hours (RTH)
- formatDate, The format in which the incoming bars' date should be presented. Note that for day bars, only yyyyMMdd format is available.
- keepUpToDate, Whether a subscription is made to return updates of unfinished real time bars as they are available (True), or all data is returned on a one-time basis (False). Available starting with API v973.03+ and TWS v965+. If True, and endDateTime cannot be specified.
For example, making a request with an end date and time of "20160127 23:59:59", a duration string of "3 D" and a bar size of "1 hour" will return three days worth of 1 hour bars data in which the most recent bar will be the closest possible to 20160127 23:59:59.
** Python **
queryTime = (datetime.datetime.today() - datetime.timedelta(days=180)).strftime("%Y%m%d %H:%M:%S")
self.reqHistoricalData(4102, ContractSamples.EurGbpFx(), queryTime,"1 M", "1 day", "MIDPOINT", 1, 1, False, [])
self.reqHistoricalData(4103, ContractSamples.EuropeanStock(), queryTime,"10 D", "1 min", "TRADES", 1, 1, False, [])
self.reqHistoricalData(4104, ContractSamples.EurGbpFx(), "","1 M", "1 day", "MIDPOINT", 1, 1, True, [])
** Java **
Calendar cal = Calendar.getInstance();
cal.add(Calendar.MONTH, -6);
SimpleDateFormat form = new SimpleDateFormat("yyyyMMdd HH:mm:ss");
String formatted = form.format(cal.getTime());
client.reqHistoricalData(4001, ContractSamples.EurGbpFx(), formatted, "1 M", "1 day", "MIDPOINT", 1, 1, false, null);
client.reqHistoricalData(4002, ContractSamples.EuropeanStock(), formatted, "10 D", "1 min", "TRADES", 1, 1, false, null);
Thread.sleep(2000);
/*** Canceling historical data requests ***/
client.cancelHistoricalData(4001);
client.cancelHistoricalData(4002);
The daily bar size has several unique characteristics. This is true both in TWS and the API:
- For futures, the close price of daily bars can be the settlement price if provided by the exchange. Generally the official settlement price is not available until several hours after a trading session closes. The Friday settlement price will sometimes not be available until Saturday.
- A daily bar will refer to a trading session which may cross calendar days. In that case the date of the bar will correspond to the day on which the bar closes.
Receiving Historical Bar Data
The historical data will be delivered via the LYNXApi.EWrapper.historicalData method in the form of candlesticks. The time zone of returned bars is the time zone chosen in TWS on the login screen. If reqHistoricalData was invoked with keepUpToDate = false, once all candlesticks have been received the LYNXApi.EWrapper.historicalDataEnd marker will be sent. Otherwise updates of the most recent partial five-second bar will continue to be returned in real time to LYNXApi.EWrapper.historicalDataUpdate . The keepUpToDate functionality can only be used with bar sizes 5 seconds or greater and requires the endDate is set as the empty string.
[!NOTE]
- LYNX's historical data feed is filtered for some types of trades which generally occur away from the NBBO such as combos, block trades, and derivatives. For that reason the historical data volume will be lower than an unfiltered historical data feed.
- LYNX does not maintain separate historical data for combos. Historical data returned for a combo contract will be the sum of data from the individual legs.
** Python **
class TestWrapper(wrapper.EWrapper):
def historicalData(self, reqId:int, bar: BarData):
print("HistoricalData. ReqId:", reqId, "BarData.", bar)
def historicalDataEnd(self, reqId: int, start: str, end: str):
super().historicalDataEnd(reqId, start, end
print("HistoricalDataEnd. ReqId:", reqId, "from", start, "to",
end)
** Java **
public class EWrapperImpl implements EWrapper {
@Override
public void historicalData(int reqId, Bar bar) {
System.out.println("HistoricalData. "+reqId+" - Date: "+bar.time()+", Open: "+bar.open()+", High: "+bar.high()+", Low: "+bar.low()+", Close: "+bar.close()+", Volume: "+bar.volume()+", Count: "+bar.count()+", WAP: "+bar.wap());
}
@Override
public void historicalDataEnd(int reqId, String startDateStr, String endDateStr) {
System.out.println("HistoricalDataEnd. "+reqId+" - Start Date: "+startDateStr+", End Date: "+endDateStr);
}
** Python **
def historicalDataUpdate(self, reqId: int, bar: BarData):
print("HistoricalDataUpdate. ReqId:", reqId, "BarData.", bar)
** Java **
@Override
public void historicalDataUpdate(int reqId, Bar bar) {
System.out.println("HistoricalDataUpdate. "+reqId+" - Date: "+bar.time()+", Open: "+bar.open()+", High: "+bar.high()+", Low: "+bar.low()+", Close: "+bar.close()+", Volume: "+bar.volume()+", Count: "+bar.count()+", WAP: "+bar.wap());
}
Valid Duration String units
Unit | Description |
---|---|
S | Seconds |
D | Day |
W | Week |
M | Month |
Y | Year |
Valid Bar Sizes
Size | |||||||
---|---|---|---|---|---|---|---|
1 secs | 5 secs | 10 secs | 15 secs | 30 secs | |||
1 min | 2 mins | 3 mins | 5 mins | 10 mins | 15 mins | 20 mins | 30 mins |
1 hour | 2 hours | 3 hours | 4 hours | 8 hours | |||
1 day | |||||||
1 week | |||||||
1 month |
Historical Data Types
All different kinds of historical data are returned in the form of candlesticks and as such the values return represent the state of the market during the period covered by the candlestick.
Type | Open | High | Low | Close | Volume |
---|---|---|---|---|---|
TRADES | First traded price | Highest traded price | Lowest traded price | Last traded price | Total traded volume |
MIDPOINT | Starting midpoint price | Highest midpoint price | Lowest midpoint price | Last midpoint price | N/A |
BID | Starting bid price | Highest bid price | Lowest bid price | Last bid price | N/A |
ASK | Starting ask price | Highest ask price | Lowest ask price | Last ask price | N/A |
BID_ASK | Time average bid | Max Ask | Min Bid | Time average ask | N/A |
ADJUSTED_LAST | Dividend-adjusted first traded price | Dividend-adjusted high trade | Dividend-adjusted low trade | Dividend-adjusted last trade | Total traded volume |
HISTORICAL_VOLATILITY | Starting volatility | Highest volatility | Lowest volatility | Last volatility | N/A |
OPTION_IMPLIED_VOLATILITY | Starting implied volatility | Highest implied volatility | Lowest implied volatility | Last implied volatility | N/A |
REBATE_RATE | Starting rebate rate | Highest rebate rate | Lowest rebate rate | Last rebate rate | N/A |
FEE_RATE | Starting fee rate | Highest fee rate | Lowest fee rate | Last fee rate | N/A |
YIELD_BID | Starting bid yield | Highest bid yield | Lowest bid yield | Last bid yield | N/A |
YIELD_ASK | Starting ask yield | Highest ask yield | Lowest ask yield | Last ask yield | N/A |
YIELD_BID_ASK | Time average bid yield | Highest ask yield | Lowest bid yield | Time average ask yield | N/A |
YIELD_LAST | Starting last yield | Highest last yield | Lowest last yield | Last last yield | N/A |
- TRADES data is adjusted for splits, but not dividends
- ADJUSTED_LAST data is adjusted for splits and dividends. Requires TWS 967+.
Available Data per Product
Product Type | TRADES | MIDPOINT | BID | ASK | BID_ASK | HISTORICAL_VOLATILITY |
---|---|---|---|---|---|---|
Stocks | Y | Y | Y | Y | Y | Y |
Commodities | N | Y | Y | Y | Y | N |
Options | Y | Y | Y | Y | Y | N |
Futures | Y | Y | Y | Y | Y | N |
FOPs | Y | Y | Y | Y | Y | N |
ETFs | Y | Y | Y | Y | Y | Y |
Warrants | Y | Y | Y | Y | Y | N |
Structured Products | Y | Y | Y | Y | Y | N |
SSFs | Y | Y | Y | Y | Y | N |
Forex | N | Y | Y | Y | Y | N |
Metals | Y | Y | Y | Y | Y | N |
Indices | Y | N | N | N | N | Y |
Bonds* | Y | Y | Y | Y | Y | N |
Funds | N | Y | Y | Y | Y | N |
CFDs* | N | Y | Y | Y | Y | N |
Product type | OPTION_IMPLIED_VOLATILITY | YIELD_BID | YIELD_ASK | YIELD_BID_ASK | YIELD_LAST |
---|---|---|---|---|---|
Stocks | Y | N | N | N | N |
Commodities | N | N | N | N | N |
Options | N | N | N | N | N |
Futures | N | N | N | N | N |
FOPs | N | N | N | N | N |
ETFs | Y | N | N | N | N |
Warrants | N | N | N | N | N |
Structured Products | N | N | N | N | N |
SSFs | N | N | N | N | N |
Forex | N | N | N | N | N |
Metals | N | N | N | N | N |
Indices | Y | N | N | N | N |
Bonds* | N | Y | Y | Y | Y |
Funds | N | N | N | N | N |
CFDs* | N | N | N | N | N |
- Yield historical data only available for corporate bonds