Add (hacky) forex pair support to `Client.find_contract()`

fix_forex
Tyler Goodlet 2022-07-12 16:51:06 -04:00
parent e0491cf2e7
commit 6a1a62d8c0
1 changed files with 55 additions and 14 deletions

View File

@ -205,6 +205,19 @@ _adhoc_futes_set = {
} }
# taken from list here:
# https://www.interactivebrokers.com/en/trading/products-spot-currencies.php
_adhoc_fiat_set = set((
'USD, AED, AUD, CAD,'
'CHF, CNH, CZK, DKK,'
'EUR, GBP, HKD, HUF,'
'ILS, JPY, MXN, NOK,'
'NZD, PLN, RUB, SAR,'
'SEK, SGD, TRY, ZAR'
).split(' ,')
)
# map of symbols to contract ids # map of symbols to contract ids
_adhoc_symbol_map = { _adhoc_symbol_map = {
# https://misc.interactivebrokers.com/cstools/contract_info/v3.10/index.php?action=Conid%20Info&wlId=IB&conid=69067924 # https://misc.interactivebrokers.com/cstools/contract_info/v3.10/index.php?action=Conid%20Info&wlId=IB&conid=69067924
@ -480,6 +493,14 @@ class Client:
except RequestError as err: except RequestError as err:
log.warning(err.message) log.warning(err.message)
# forex pairs
elif sectype == 'CASH':
dst, src = tract.localSymbol.split('.')
pair_key = "/".join([dst, src])
tract.exchange = 'FOREX'
results[f'{pair_key}.forex'] = tract
results.pop(key)
return results return results
async def get_fute( async def get_fute(
@ -521,7 +542,7 @@ class Client:
async def find_contract( async def find_contract(
self, self,
pattern: str, pattern: str,
currency: str = 'USD', currency: str = '',
**kwargs, **kwargs,
) -> Contract: ) -> Contract:
@ -537,26 +558,44 @@ class Client:
# XXX UPDATE: we can probably do the tick/trades scraping # XXX UPDATE: we can probably do the tick/trades scraping
# inside our eventkit handler instead to bypass this entirely? # inside our eventkit handler instead to bypass this entirely?
# fqsn parsing stage
# ------------------
if '.ib' in pattern: if '.ib' in pattern:
from ..data._source import unpack_fqsn from ..data._source import unpack_fqsn
broker, symbol, expiry = unpack_fqsn(pattern) broker, symbol, expiry = unpack_fqsn(pattern)
else: else:
symbol = pattern symbol = pattern
# try: # another hack for forex pairs lul.
# # give the cache a go if (
# return self._contracts[symbol] '.forex' in symbol
# except KeyError: # and not '.ib' in pattern
# log.debug(f'Looking up contract for {symbol}') # or '/' in symbol
expiry: str = '' ):
if symbol.count('.') > 1: exch = 'FOREX'
symbol, _, expiry = symbol.rpartition('.') symbol = symbol.removesuffix('.forex')
if '/' in symbol:
symbol, currency = symbol.split('/')
# use heuristics to figure out contract "type" else:
sym, exch = symbol.upper().rsplit('.', maxsplit=1) # try:
# # give the cache a go
# return self._contracts[symbol]
# except KeyError:
# log.debug(f'Looking up contract for {symbol}')
expiry: str = ''
if symbol.count('.') > 1:
symbol, _, expiry = symbol.rpartition('.')
# use heuristics to figure out contract "type"
sym, exch = symbol.upper().rsplit('.', maxsplit=1)
qualify: bool = True qualify: bool = True
# contract searching stage
# ------------------------
# futes # futes
if exch in _futes_venues: if exch in _futes_venues:
if expiry: if expiry:
@ -578,10 +617,11 @@ class Client:
qualify = False qualify = False
elif exch in ('FOREX'): elif exch in ('FOREX'):
currency = '' # if '/' in symbol:
symbol, currency = sym.split('/') # currency = ''
# symbol, currency = sym.split('/')
con = ibis.Forex( con = ibis.Forex(
symbol=symbol, pair=''.join((symbol, currency)),
currency=currency, currency=currency,
) )
con.bars_kwargs = {'whatToShow': 'MIDPOINT'} con.bars_kwargs = {'whatToShow': 'MIDPOINT'}
@ -649,6 +689,7 @@ class Client:
async def get_sym_details( async def get_sym_details(
self, self,
symbol: str, symbol: str,
) -> tuple[Contract, Ticker, ContractDetails]: ) -> tuple[Contract, Ticker, ContractDetails]:
contract = await self.find_contract(symbol) contract = await self.find_contract(symbol)