Add 1m ohlc sample rate support to `Client.bars()`; frame query is 1 day

clears_table_events
Tyler Goodlet 2022-09-15 11:42:08 -04:00
parent 5144299f4f
commit 1adf5fb9c0
1 changed files with 31 additions and 39 deletions

View File

@ -78,26 +78,11 @@ _time_units = {
'h': ' hours', 'h': ' hours',
} }
_time_frames = { _bar_sizes = {
'1s': '1 Sec', 1: '1 Sec',
'5s': '5 Sec', 60: '1 min',
'30s': '30 Sec', 60*60: '1 hour',
'1m': 'OneMinute', 24*60*60: '1 day',
'2m': 'TwoMinutes',
'3m': 'ThreeMinutes',
'4m': 'FourMinutes',
'5m': 'FiveMinutes',
'10m': 'TenMinutes',
'15m': 'FifteenMinutes',
'20m': 'TwentyMinutes',
'30m': 'HalfHour',
'1h': 'OneHour',
'2h': 'TwoHours',
'4h': 'FourHours',
'D': 'OneDay',
'W': 'OneWeek',
'M': 'OneMonth',
'Y': 'OneYear',
} }
_show_wap_in_history: bool = False _show_wap_in_history: bool = False
@ -338,19 +323,36 @@ class Client:
start_dt: Union[datetime, str] = "1970-01-01T00:00:00.000000-05:00", start_dt: Union[datetime, str] = "1970-01-01T00:00:00.000000-05:00",
end_dt: Union[datetime, str] = "", end_dt: Union[datetime, str] = "",
sample_period_s: str = 1, # ohlc sample period # ohlc sample period in seconds
period_count: int = int(2e3), # <- max per 1s sample query sample_period_s: int = 1,
) -> list[dict[str, Any]]: ) -> list[dict[str, Any]]:
''' '''
Retreive OHLCV bars for a fqsn over a range to the present. Retreive OHLCV bars for a fqsn over a range to the present.
''' '''
# See API docs here:
# https://interactivebrokers.github.io/tws-api/historical_data.html
bars_kwargs = {'whatToShow': 'TRADES'} bars_kwargs = {'whatToShow': 'TRADES'}
# NOTE: pacing violations exist for higher sample rates:
# https://interactivebrokers.github.io/tws-api/historical_limitations.html#pacing_violations
# Also see note on duration limits being lifted on 1m+ periods,
# but they say "use with discretion":
# https://interactivebrokers.github.io/tws-api/historical_limitations.html#non-available_hd
bar_size, duration = {
1: ('1 secs', f'{int(2e3)} S'),
# TODO: benchmark >1 D duration on query to see if
# throughput can be made faster during backfilling.
60: ('1 min', '1 D'),
}[sample_period_s]
global _enters global _enters
# log.info(f'REQUESTING BARS {_enters} @ end={end_dt}') # log.info(f'REQUESTING BARS {_enters} @ end={end_dt}')
print(f'REQUESTING BARS {_enters} @ end={end_dt}') print(
f"REQUESTING {duration}'s worth {bar_size} BARS\n"
f'{_enters} @ end={end_dt}"'
)
if not end_dt: if not end_dt:
end_dt = '' end_dt = ''
@ -360,30 +362,20 @@ class Client:
contract = (await self.find_contracts(fqsn))[0] contract = (await self.find_contracts(fqsn))[0]
bars_kwargs.update(getattr(contract, 'bars_kwargs', {})) bars_kwargs.update(getattr(contract, 'bars_kwargs', {}))
# _min = min(2000*100, count)
bars = await self.ib.reqHistoricalDataAsync( bars = await self.ib.reqHistoricalDataAsync(
contract, contract,
endDateTime=end_dt, endDateTime=end_dt,
formatDate=2, formatDate=2,
# time history length values format:
# ``durationStr=integer{SPACE}unit (S|D|W|M|Y)``
# OHLC sampling values: # OHLC sampling values:
# 1 secs, 5 secs, 10 secs, 15 secs, 30 secs, 1 min, 2 mins, # 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, # 3 mins, 5 mins, 10 mins, 15 mins, 20 mins, 30 mins,
# 1 hour, 2 hours, 3 hours, 4 hours, 8 hours, 1 day, 1W, 1M # 1 hour, 2 hours, 3 hours, 4 hours, 8 hours, 1 day, 1W, 1M
# barSizeSetting='1 secs', barSizeSetting=bar_size,
# durationStr='{count} S'.format(count=15000 * 5), # time history length values format:
# durationStr='{count} D'.format(count=1), # ``durationStr=integer{SPACE}unit (S|D|W|M|Y)``
# barSizeSetting='5 secs', durationStr=duration,
durationStr='{count} S'.format(count=period_count),
# barSizeSetting='5 secs',
barSizeSetting='1 secs',
# barSizeSetting='1 min',
# always use extended hours # always use extended hours
useRTH=False, useRTH=False,
@ -394,8 +386,8 @@ class Client:
# whatToShow='TRADES', # whatToShow='TRADES',
) )
if not bars: if not bars:
# TODO: raise underlying error here # trigger ``NoData`` raise by ``get_bars()`` caller.
raise ValueError(f"No bars retreived for {fqsn}?") return None
nparr = bars_to_np(bars) nparr = bars_to_np(bars)
return bars, nparr return bars, nparr