Beispiel #1
0
    def test_process_order_fill_event_buy(self):
        amount = Decimal("1")
        price = Decimal("9000")
        event = OrderFilledEvent(
            timestamp=1,
            order_id="order1",
            trading_pair=self.trading_pair,
            trade_type=TradeType.BUY,
            order_type=OrderType.LIMIT,
            price=price,
            amount=amount,
            trade_fee=AddedToCostTradeFee(percent=Decimal("0"), flat_fees=[]),
        )
        # first event creates DB record
        self.delegate.process_order_fill_event(event)
        with self.trade_fill_sql.get_new_session() as session:
            count = session.query(InventoryCost).count()
            self.assertEqual(count, 1)

            # second event causes update to existing record
            self.delegate.process_order_fill_event(event)
            record = InventoryCost.get_record(session, self.base_asset,
                                              self.quote_asset)
            self.assertEqual(record.base_volume, amount * 2)
            self.assertEqual(record.quote_volume, price * 2)
    def get_price(self) -> Optional[Decimal]:
        record = InventoryCost.get_record(self._session, self.base_asset,
                                          self.quote_asset)

        if record is None or record.base_volume is None or record.base_volume is None:
            return None

        try:
            price = record.quote_volume / record.base_volume
        except InvalidOperation:
            # decimal.InvalidOperation: [<class 'decimal.DivisionUndefined'>] - both volumes are 0
            return None
        return Decimal(price)
    def get_price(self) -> Optional[Decimal]:
        record = InventoryCost.get_record(self._session, self.base_asset,
                                          self.quote_asset)

        if record is None or record.base_volume is None or record.base_volume is None:
            return None

        try:
            price = record.quote_volume / record.base_volume
        except InvalidOperation:
            # use both volume = 0
            return None
        return Decimal(price)
Beispiel #4
0
    def get_price(self) -> Optional[Decimal]:
        with self.sql_manager.get_new_session() as session:
            with session.begin():
                record = InventoryCost.get_record(session, self.base_asset,
                                                  self.quote_asset)

                if record is None or record.base_volume is None or record.base_volume is None:
                    return None

                try:
                    price = record.quote_volume / record.base_volume
                except InvalidOperation:
                    return None
                return Decimal(price)
Beispiel #5
0
    def process_order_fill_event(self, fill_event: OrderFilledEvent) -> None:
        base_asset, quote_asset = fill_event.trading_pair.split("-")
        quote_volume = fill_event.amount * fill_event.price
        base_volume = fill_event.amount

        for fee_asset, fee_amount in fill_event.trade_fee.flat_fees:
            if fill_event.trade_type == TradeType.BUY:
                if fee_asset == base_asset:
                    base_volume -= fee_amount
                elif fee_asset == quote_asset:
                    quote_volume += fee_amount
                else:
                    # Ok, some other asset used (like BNB), assume that we paid in base asset for simplicity
                    base_volume /= 1 + fill_event.trade_fee.percent
            else:
                if fee_asset == base_asset:
                    base_volume += fee_amount
                elif fee_asset == quote_asset:
                    # TODO: with new logic, this quote volume adjustment does not impacts anything
                    quote_volume -= fee_amount
                else:
                    # Ok, some other asset used (like BNB), assume that we paid in base asset for simplicity
                    base_volume /= 1 + fill_event.trade_fee.percent

        with self.sql_manager.get_new_session() as session:
            with session.begin():
                if fill_event.trade_type == TradeType.SELL:
                    record = InventoryCost.get_record(session, base_asset,
                                                      quote_asset)
                    if not record:
                        raise RuntimeError(
                            "Sold asset without having inventory price set. This should not happen."
                        )

                    # We're keeping initial buy price intact. Profits are not changing inventory price intentionally.
                    quote_volume = -(Decimal(record.quote_volume /
                                             record.base_volume) * base_volume)
                    base_volume = -base_volume

                InventoryCost.add_volume(session, base_asset, quote_asset,
                                         base_volume, quote_volume)
Beispiel #6
0
    def test_process_order_fill_event_sell(self):
        amount = Decimal("1")
        price = Decimal("9000")

        # Test when no records
        self.assertIsNone(self.delegate.get_price())

        with self.trade_fill_sql.get_new_session() as session:
            with session.begin():
                record = InventoryCost(
                    base_asset=self.base_asset,
                    quote_asset=self.quote_asset,
                    base_volume=amount,
                    quote_volume=amount * price,
                )
                session.add(record)

        amount_sell = Decimal("0.5")
        price_sell = Decimal("10000")
        event = OrderFilledEvent(
            timestamp=1,
            order_id="order1",
            trading_pair=self.trading_pair,
            trade_type=TradeType.SELL,
            order_type=OrderType.LIMIT,
            price=price_sell,
            amount=amount_sell,
            trade_fee=AddedToCostTradeFee(percent=Decimal("0"), flat_fees=[]),
        )

        self.delegate.process_order_fill_event(event)
        with self.trade_fill_sql.get_new_session() as session:
            record = InventoryCost.get_record(session, self.base_asset,
                                              self.quote_asset)
            # Remaining base volume reduced by sold amount
            self.assertEqual(record.base_volume, amount - amount_sell)
            # Remaining quote volume has been reduced using original price
            self.assertEqual(record.quote_volume, amount_sell * price)
    def process_order_fill_event(self, fill_event: OrderFilledEvent) -> None:
        base_asset, quote_asset = fill_event.trading_pair.split("-")
        quote_volume = fill_event.amount * fill_event.price
        base_volume = fill_event.amount

        for fee_asset, fee_amount in fill_event.trade_fee.flat_fees:
            if fill_event.trade_type == TradeType.BUY:
                if fee_asset == base_asset:
                    base_volume -= fee_amount
                elif fee_asset == quote_asset:
                    quote_volume += fee_amount
                else:
                    # used for exchange native token used as base fee .
                    base_volume /= 1 + fill_event.trade_fee.percent
            else:
                if fee_asset == base_asset:
                    base_volume += fee_amount
                elif fee_asset == quote_asset:
                    # volume adjustment with new logic.
                    quote_volume -= fee_amount
                else:
                    base_volume /= 1 + fill_event.trade_fee.percent

        if fill_event.trade_type == TradeType.SELL:
            record = InventoryCost.get_record(self._session, base_asset,
                                              quote_asset)
            if not record:
                raise RuntimeError(
                    "Sold asset without having inventory price set. This should not happen."
                )

            #  keeping initial buy price intact. Profits are not changing inventory price intentionally.
            quote_volume = -(Decimal(record.quote_volume / record.base_volume)
                             * base_volume)
            base_volume = -base_volume

        InventoryCost.add_volume(self._session, base_asset, quote_asset,
                                 base_volume, quote_volume)