def _constructInstrument(contract): name = contract.localSymbol if contract.localSymbol else contract.symbol brokerId = str(contract.conId) brokerExchange = contract.exchange currency = Instrument(name=contract.currency, type=InstrumentType.CURRENCY) if contract.secType == "STK": type = InstrumentType.EQUITY elif contract.secType == "BOND": type = InstrumentType.BOND elif contract.secType == "OPT": type = InstrumentType.OPTION elif contract.secType == "FUT": type = InstrumentType.FUTURE elif contract.secType == "CASH": type = InstrumentType.PAIR elif contract.secType == "FOP": type = InstrumentType.FUTURESOPTION elif contract.secType == "FUND": type = InstrumentType.MUTUALFUND elif contract.secType == "CMDTY": type = InstrumentType.COMMODITIES elif contract.secType == "BAG": type = InstrumentType.SPREAD else: raise NotImplementedError() return Instrument(name=name, type=type, exchanges=[], brokerExchange=brokerExchange, brokerId=brokerId, currency=currency)
def restore(self, filename_prefix): with open('{}.prices.json'.format(filename_prefix), 'r') as fp: jsn = json.load(fp) self._prices = { Instrument.fromJson(json.loads(k)): [(p1, datetime.fromtimestamp(p2)) for p1, p2 in v] for k, v in jsn.items() } with open('{}.trades.json'.format(filename_prefix), 'r') as fp: jsn = json.load(fp) self._trades = { Instrument.fromJson(json.loads(k)): [Trade.fromJson(x) for x in v] for k, v in jsn.items() } with open('{}.active_by_inst.json'.format(filename_prefix), 'r') as fp: jsn = json.load(fp) self._active_positions_by_instrument = { Instrument.fromJson(json.loads(k)): [Position.fromJson(vv) for vv in v] for k, v in jsn.items() } with open('{}.active_by_strat.json'.format(filename_prefix), 'r') as fp: jsn = json.load(fp) self._active_positions_by_strategy = { k: { Instrument.fromJson(json.loads(kk)): Position.fromJson(vv) for kk, vv in v.items() } for k, v in jsn.items() }
async def instruments(self): '''get list of available instruments''' instruments = [] symbols = self._client.symbols() for record in symbols: if not record['isEnabled'] or not record['type'] or record[ 'type'] == 'temp': continue symbol = record['symbol'] brokerExchange = record['exchange'] type = _iex_instrument_types[record['type']] currency = Instrument(type=InstrumentType.CURRENCY, name=record['currency']) try: inst = Instrument(name=symbol, type=type, exchange=self.exchange(), brokerExchange=brokerExchange, currency=currency) except AssertionError: # Happens sometimes on sandbox continue instruments.append(inst) return instruments
async def instruments(self) -> List[Instrument]: """get list of available instruments""" instruments = [] symbols = self._client.symbols() for record in symbols: if (not record["isEnabled"] or not record["type"] or record["type"] == "temp"): continue symbol = record["symbol"] brokerExchange = record["exchange"] type = _iex_instrument_types[record["type"]] currency = Instrument(type=InstrumentType.CURRENCY, name=record["currency"]) try: inst = Instrument( name=symbol, type=type, exchange=self.exchange(), brokerExchange=brokerExchange, currency=currency, ) except AssertionError: # Happens sometimes on sandbox continue instruments.append(inst) return instruments
def test_instrument(self): E1 = ExchangeType("E1") E2 = ExchangeType("E2") E3 = ExchangeType("E3") i1 = Instrument( "TestInst", exchange=E1, broker_id="1", ) i2 = Instrument( "TestInst", exchange=E2, broker_id="2", broker_exchange="test", ) i3 = Instrument( "TestInst", exchange=E3, broker_id="3", ) assert i1.tradingLines() == [i1, i2, i3] assert i2.tradingLines() == [i1, i2, i3] assert i3.tradingLines() == [i1, i2, i3]
def test_instrument_calendar_getter(self): t = TradingDay() e = ExchangeType("test-exchange") i = Instrument( "test", exchange=e, trading_day=t, ) assert i.tradingDay(e) == t
async def connect(self): with open(self._filename) as csvfile: self._reader = csv.DictReader(csvfile, delimiter=',') for row in self._reader: order = Order(volume=float(row['volume']), price=float(row['close']), side=Side.BUY, exchange=self.exchange(), instrument=Instrument( row['symbol'].split('-')[0], InstrumentType(row['symbol'].split('-')[1].upper()) ) ) order.filled = float(row['volume']) if 'time' in row: order.timestamp = datetime.fromtimestamp(float(row['time'])) elif 'date' in row: order.timestamp = datetime.fromisoformat(row['date']) elif 'datetime' in row: order.timestamp = datetime.fromisoformat(row['datetime']) self._data.append(Trade(volume=float(row['volume']), price=float(row['close']), maker_orders=[], taker_order=order))
async def connect(self) -> None: with open(self._filename) as csvfile: self._reader = csv.DictReader(csvfile, delimiter=",") for row in self._reader: order = Order( volume=float(row["volume"]), price=float(row["close"]), side=Side.BUY, exchange=self.exchange(), instrument=Instrument( row["symbol"].split("-")[0], InstrumentType(row["symbol"].split("-")[1].upper()), ), filled=float(row["volume"]), ) if "time" in row: order.timestamp = datetime.fromtimestamp(float( row["time"])) elif "date" in row: order.timestamp = datetime.fromisoformat(row["date"]) elif "datetime" in row: order.timestamp = datetime.fromisoformat(row["datetime"]) self._data.append( Trade( volume=float(row["volume"]), price=float(row["close"]), maker_orders=[], taker_order=order, ))
def __init__(self, trading_type: TradingType, verbose: bool) -> None: super().__init__(ExchangeType("testharness")) self._trading_type = trading_type self._verbose = verbose self._instrument = Instrument("Test.inst", InstrumentType.EQUITY) self._id = 0 self._start = datetime.now() - timedelta(days=30) self._client_order: Optional[Order] = None
def __init__(self, trading_type, verbose): super().__init__(ExchangeType('testharness')) self._trading_type = trading_type self._verbose = verbose self._instrument = Instrument('Test.inst', InstrumentType.EQUITY) self._id = 0 self._start = datetime.now() - timedelta(days=30) self._client_order = None
def test_price_level_iter(self): pl = _PriceLevel(5, _Collector()) orders = [ Order(10 + i, 5, Side.BUY, Instrument('TEST'), ExchangeType(""), 0.0, OrderType.LIMIT, OrderFlag.NONE, None) for i in range(2) ] for o in orders: # This causes a segfault pl.add(o) for o, op in zip(orders, pl): assert o == op
# type: ignore import pytest from aat.common import _in_cpp from aat.core import Order, Instrument, ExchangeType _INSTRUMENT = Instrument("TE.ST") class TestOrder: def test_stop_order_validation(self): if _in_cpp(): return with pytest.raises(AssertionError): Order( volume=0.0, price=5.0, side=Order.Sides.SELL, exchange=ExchangeType(""), order_type=Order.Types.STOP, stop_target=Order( volume=0.5, price=5.0, side=Order.Sides.SELL, exchange=ExchangeType(""), order_type=Order.Types.STOP, instrument=_INSTRUMENT, ), instrument=_INSTRUMENT, )
# type: ignore import pydantic import pytest from datetime import datetime from aat.common import _in_cpp from aat.core import Order, Instrument, ExchangeType _INSTRUMENT = Instrument('TE.ST') class TestOrder: def test_stop_order_validation(self): if _in_cpp(): return with pytest.raises(pydantic.ValidationError): Order(id=1, timestamp=datetime.now(), volume=0.0, price=5.0, side=Order.Sides.SELL, exchange=ExchangeType(''), order_type=Order.Types.STOP, stop_target=Order( id=1, timestamp=datetime.now(), volume=0.5, price=5.0, side=Order.Sides.SELL, exchange=ExchangeType(''), order_type=Order.Types.STOP,
async def tick( self) -> AsyncGenerator[Any, Event]: # type: ignore[override] """return data from exchange""" if self._timeframe == "live": data: Deque[dict] = deque() def _callback(record: dict) -> None: data.append(record) self._client.tradesSSE( symbols=",".join([i.name for i in self._subscriptions]), on_data=_callback, ) while True: while data: record = data.popleft() volume = record["volume"] price = record["price"] instrument = Instrument(record["symbol"], InstrumentType.EQUITY) o = Order( volume=volume, price=price, side=Side.BUY, instrument=instrument, exchange=self.exchange(), ) t = Trade(volume=volume, price=price, taker_order=o, maker_orders=[]) yield Event(type=EventType.TRADE, target=t) await asyncio.sleep(0) else: dfs = [] insts = set() if self._timeframe != "1d": for i in tqdm(self._subscriptions, desc="Fetching data..."): if i.name in insts: # already fetched the data, multiple subscriptions continue if self._cache_data: # first, check if we have this data and its cached already os.makedirs("_aat_data", exist_ok=True) data_filename = os.path.join( "_aat_data", "iex_{}_{}_{}_{}.pkl".format( i.name, self._timeframe, datetime.now().strftime("%Y%m%d"), "sand" if self._is_sandbox else "", ), ) if os.path.exists(data_filename): print("using cached IEX data for {}".format( i.name)) df = pd.read_pickle(data_filename) else: df = self._client.chartDF( i.name, timeframe=self._timeframe) df.to_pickle(data_filename) else: df = self._client.chartDF(i.name, timeframe=self._timeframe) df = df[["close", "volume"]] df.columns = [ "close:{}".format(i.name), "volume:{}".format(i.name) ] dfs.append(df) insts.add(i.name) data_frame = pd.concat(dfs, axis=1) data_frame.sort_index(inplace=True) data_frame = data_frame.groupby(data_frame.index).last() data_frame.drop_duplicates(inplace=True) data_frame.fillna(method="ffill", inplace=True) else: for i in tqdm(self._subscriptions, desc="Fetching data..."): if i.name in insts: # already fetched the data, multiple subscriptions continue date = self._start_date subdfs = [] while date <= self._end_date: if self._cache_data: # first, check if we have this data and its cached already os.makedirs("_aat_data", exist_ok=True) data_filename = os.path.join( "_aat_data", "iex_{}_{}_{}_{}.pkl".format( i.name, self._timeframe, date, "sand" if self._is_sandbox else "", ), ) if os.path.exists(data_filename): print( "using cached IEX data for {} - {}".format( i.name, date)) df = pd.read_pickle(data_filename) else: df = self._client.chartDF( i.name, timeframe="1d", date=date.strftime("%Y%m%d")) df.to_pickle(data_filename) else: df = self._client.chartDF( i.name, timeframe="1d", date=date.strftime("%Y%m%d")) if not df.empty: df = df[["average", "volume"]] df.columns = [ "close:{}".format(i.name), "volume:{}".format(i.name), ] subdfs.append(df) date += timedelta(days=1) dfs.append(pd.concat(subdfs)) insts.add(i.name) data_frame = pd.concat(dfs, axis=1) data_frame.index = [ x + timedelta(hours=int(y.split(":")[0]), minutes=int(y.split(":")[1])) for x, y in data_frame.index ] data_frame = data_frame.groupby(data_frame.index).last() data_frame.drop_duplicates(inplace=True) data_frame.fillna(method="ffill", inplace=True) for index in data_frame.index: for i in self._subscriptions: volume = data_frame.loc[index]["volume:{}".format(i.name)] price = data_frame.loc[index]["close:{}".format(i.name)] if volume == 0: continue o = Order( volume=volume, price=price, side=Side.BUY, instrument=i, exchange=self.exchange(), filled=volume, timestamp=index.to_pydatetime(), ) t = Trade(volume=volume, price=price, taker_order=o, maker_orders=[]) yield Event(type=EventType.TRADE, target=t) await asyncio.sleep(0) while self._queued_orders: order = self._queued_orders.popleft() order.timestamp = index order.filled = order.volume t = Trade( volume=order.volume, price=order.price, taker_order=order, maker_orders=[], my_order=order, ) yield Event(type=EventType.TRADE, target=t) await asyncio.sleep(0)
async def tick(self): '''return data from exchange''' if self._timeframe == 'live': data = deque() def _callback(record): data.append(record) self._client.tradesSSE(symbols=",".join( [i.name for i in self._subscriptions]), on_data=_callback) while True: while data: record = data.popleft() volume = record['volume'] price = record['price'] instrument = Instrument(record['symbol'], InstrumentType.EQUITY) o = Order(volume=volume, price=price, side=Side.BUY, instrument=instrument, exchange=self.exchange()) t = Trade(volume=volume, price=price, taker_order=o, maker_orders=[]) yield Event(type=EventType.TRADE, target=t) await asyncio.sleep(0) else: dfs = [] insts = set() if self._timeframe != '1d': for i in tqdm(self._subscriptions, desc="Fetching data..."): if i.name in insts: # already fetched the data, multiple subscriptions continue if self._cache_data: # first, check if we have this data and its cached already os.makedirs('_aat_data', exist_ok=True) data_filename = os.path.join( '_aat_data', 'iex_{}_{}_{}_{}.pkl'.format( i.name, self._timeframe, datetime.now().strftime('%Y%m%d'), 'sand' if self._is_sandbox else '')) if os.path.exists(data_filename): print('using cached IEX data for {}'.format( i.name)) df = pd.read_pickle(data_filename) else: df = self._client.chartDF( i.name, timeframe=self._timeframe) df.to_pickle(data_filename) else: df = self._client.chartDF(i.name, timeframe=self._timeframe) df = df[['close', 'volume']] df.columns = [ 'close:{}'.format(i.name), 'volume:{}'.format(i.name) ] dfs.append(df) insts.add(i.name) data = pd.concat(dfs, axis=1) data.sort_index(inplace=True) data = data.groupby(data.index).last() data.drop_duplicates(inplace=True) data.fillna(method='ffill', inplace=True) else: for i in tqdm(self._subscriptions, desc="Fetching data..."): if i.name in insts: # already fetched the data, multiple subscriptions continue date = self._start_date subdfs = [] while date <= self._end_date: if self._cache_data: # first, check if we have this data and its cached already os.makedirs('_aat_data', exist_ok=True) data_filename = os.path.join( '_aat_data', 'iex_{}_{}_{}_{}.pkl'.format( i.name, self._timeframe, date, 'sand' if self._is_sandbox else '')) if os.path.exists(data_filename): print( 'using cached IEX data for {} - {}'.format( i.name, date)) df = pd.read_pickle(data_filename) else: df = self._client.chartDF( i.name, timeframe='1d', date=date.strftime('%Y%m%d')) df.to_pickle(data_filename) else: df = self._client.chartDF( i.name, timeframe='1d', date=date.strftime('%Y%m%d')) if not df.empty: df = df[['average', 'volume']] df.columns = [ 'close:{}'.format(i.name), 'volume:{}'.format(i.name) ] subdfs.append(df) date += timedelta(days=1) dfs.append(pd.concat(subdfs)) insts.add(i.name) data = pd.concat(dfs, axis=1) data.index = [ x + timedelta(hours=int(y.split(':')[0]), minutes=int(y.split(':')[1])) for x, y in data.index ] data = data.groupby(data.index).last() data.drop_duplicates(inplace=True) data.fillna(method='ffill', inplace=True) for index in data.index: for i in self._subscriptions: volume = data.loc[index]['volume:{}'.format(i.name)] price = data.loc[index]['close:{}'.format(i.name)] if volume == 0: continue o = Order(volume=volume, price=price, side=Side.BUY, instrument=i, exchange=self.exchange()) o.filled = volume o.timestamp = index.to_pydatetime() t = Trade(volume=volume, price=price, taker_order=o, maker_orders=[]) yield Event(type=EventType.TRADE, target=t) await asyncio.sleep(0) while self._queued_orders: order = self._queued_orders.popleft() order.timestamp = index order.filled = order.volume t = Trade(volume=order.volume, price=order.price, taker_order=order, maker_orders=[]) t.my_order = order yield Event(type=EventType.TRADE, target=t) await asyncio.sleep(0)
async def tick(self): '''return data from exchange''' if self._timeframe == 'live': data = deque() def _callback(record): data.append(record) self._client.tradesSSE(symbols=",".join([i.name for i in self._subscriptions]), on_data=_callback) while True: while data: record = data.popleft() volume = record['volume'] price = record['price'] instrument = Instrument(record['symbol'], InstrumentType.EQUITY) o = Order(volume=volume, price=price, side=Side.BUY, instrument=instrument, exchange=self.exchange()) t = Trade(volume=volume, price=price, taker_order=o, maker_orders=[]) yield Event(type=EventType.TRADE, target=t) await asyncio.sleep(0) else: dfs = [] if self._timeframe != '1d': for i in tqdm(self._subscriptions, desc="Fetching data..."): df = self._client.chartDF(i.name, timeframe=self._timeframe) df = df[['close', 'volume']] df.columns = ['close:{}'.format(i.name), 'volume:{}'.format(i.name)] dfs.append(df) data = pd.concat(dfs, axis=1) data.sort_index(inplace=True) data = data.groupby(data.index).last() data.drop_duplicates(inplace=True) data.fillna(method='ffill', inplace=True) else: for i in tqdm(self._subscriptions, desc="Fetching data..."): date = self._start_date subdfs = [] while date <= self._end_date: df = self._client.chartDF(i.name, timeframe='1d', date=date.strftime('%Y%m%d')) if not df.empty: df = df[['average', 'volume']] df.columns = ['close:{}'.format(i.name), 'volume:{}'.format(i.name)] subdfs.append(df) date += timedelta(days=1) dfs.append(pd.concat(subdfs)) data = pd.concat(dfs, axis=1) data.index = [x + timedelta(hours=int(y.split(':')[0]), minutes=int(y.split(':')[1])) for x, y in data.index] data = data.groupby(data.index).last() data.drop_duplicates(inplace=True) data.fillna(method='ffill', inplace=True) for index in data.index: for i in self._subscriptions: volume = data.loc[index]['volume:{}'.format(i.name)] price = data.loc[index]['close:{}'.format(i.name)] if volume == 0: continue o = Order(volume=volume, price=price, side=Side.BUY, instrument=i, exchange=self.exchange()) o.timestamp = index.to_pydatetime() t = Trade(volume=volume, price=price, taker_order=o, maker_orders=[]) yield Event(type=EventType.TRADE, target=t) await asyncio.sleep(0) while self._queued_orders: order = self._queued_orders.popleft() order.timestamp = index t = Trade(volume=order.volume, price=order.price, taker_order=order, maker_orders=[]) t.my_order = order yield Event(type=EventType.TRADE, target=t) await asyncio.sleep(0)