Exemple #1
0
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)
Exemple #2
0
    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()
            }
Exemple #3
0
    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
Exemple #4
0
    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
Exemple #5
0
    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]
Exemple #6
0
    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
Exemple #7
0
    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))
Exemple #8
0
    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,
                    ))
Exemple #9
0
    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
Exemple #10
0
    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
Exemple #11
0
    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
Exemple #12
0
# 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,
            )
Exemple #13
0
# 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,
Exemple #14
0
    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)
Exemple #15
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)
Exemple #16
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)