Example #1
0
    def test_over_short_position_fiat(self):
        result = market_making.simple_position_responsive_sizing(
            Money('2', 'USD'),
            Money('-3', 'USD'),
        )

        result[0].should.equal(Money('2', 'USD'))
        result[1].should.equal(Money('0', 'USD'))
Example #2
0
    def test_short_position(self):
        result = market_making.simple_position_responsive_sizing(
            Money('2', 'BTC'),
            Money('-1', 'BTC'),
        )

        result[0].should.equal(Money('2', 'BTC'))
        result[1].should.equal(Money('1', 'BTC'))
Example #3
0
    def test_over_long_position(self):
        result = market_making.simple_position_responsive_sizing(
            Money('2', 'BTC'),
            Money('3', 'BTC'),
        )

        result[0].should.equal(Money('0', 'BTC'))
        result[1].should.equal(Money('2', 'BTC'))
Example #4
0
    def tick(self, current_orders):

        self.logger.debug("--Strategy Tick--")
        self.logger.info("Current Orders: " + str(current_orders))
        # Question : Can we detect fulfilled orders ?
        # upon fulfilled order we can increase spread base on volatility
        # otherwise we should probably decrease spread to get order fulfilled....

        ob = self.primary_exchange.get_orderbook()

        self.midpoints += midpoint_lib.get_midpoint_from_orderbook(ob)

        # SAFETY
        # if (hasattr(self, 'last_ask_price') and self.last_ask_price < self.midpoint) or (hasattr(self, 'last_bid_price') and self.last_bid_price > self.midpoint):
        #     # spread was not high enough ! We likely lost money here -> correct quickly
        #     self.logger.warning("HIGH VOLATILITY encountered -> adjusting spread")
        #     self.spread *= self.spread_coef_on_loss
        #     #TODO : maybe terminate instead, with advice to change spread ? by some amount ?

        # TODO : calculate local volatility... (or reuse some indicator ??? -> see TA-lib)
        # Then based on volatility adjust spread | base_volume | tick_sleep, within exchange/user acceptable limits...
        # since we cancel and reopen order, we only need local volatility.

        # Note we probably do not want to slow down tick_sleep to not miss trend/volatility changes.
        # -> We should play on spread + base_volume only

        # OPTIMIZATION
        if self.midpoints.volatility(last=1):
            self.volat += self.midpoints.volatility(
                last=1)  # TODO : since last successful order...

            if self.volat.last()[1] < 0:
                self.logger.info("Price went down. skipping this tick...")
                # TODO : manage bear markets with shorts and leverage...

            elif self.volat.last(
            )[1] > 0:  # we only want bull micro market for now
                # We bet on the volatility to come to be the same as the one past,
                print("Volatility derivative :" + str(self.volat.deriv()))
                # TODO : define what value derivative of volatility should be

                #  and set the spread based on that.
                self.spread = self.volat.last()[1] / 2
                # TODO : reduce spread if expectation failed (order not passed), to maximize likelyhood to pass order...
                # TODO: increase spread if successful order passed, trying to maximize profit on volatile markets

                # for constant tick period, we need increased spread, and reduced base_volume
                #self.spread = self.spread_adjust_coef * (self.volat - self.last_volat) + self.spread  # adjusting spread relative to volatility

                self.logger.info("Volatility: " + str(self.volat))
                self.logger.info("Spread: " + str(self.spread))

                # TODO : take fees into account to remain profitable
                exchange_fees = self.primary_exchange.exchange_wrapper.fee
                if self.spread < exchange_fees * self.base_volume:

                    self.logger.info("Fees would be too high : " +
                                     str(exchange_fees * self.base_volume) +
                                     " vs spread of " + str(self.spread))

                else:
                    self.logger.info("Spread : " + str(self.spread) +
                                     " is larger than expected fees : " +
                                     str(exchange_fees * self.base_volume))

                    # Base volume increase means increased risk (maybe more than spread decrease).
                    # We want to increase base volume when volatility doesnt change 'much'...
                    # TODO : self.relative_volat_change = abs(self.volat - self.last_volat) / self.last_volat
                    # relative change of base_volume
                    # TODO : self.base_volume = self.base_volume_adjust_coef * (1-self.relative_volat_change) * self.base_volume + self.base_volume
                    # TODO : have a minimum volume to exchange + slowly limit to that when volatility detected.
                    # TODO : increase volume on non volatility/'less volatile than expected'... + profit ? how to measure that here ?

                    # TODO:  use profit measurement to adjust the adjust_coefs (machine learning stuff ?)...

                    # #Note : the speed of adjustment is critical to be in front of order fullfilment.
                    # -> Check control theory for a converging / asymptotic optimisation of control (yet easily reversible if needed...)

                    bid_price, ask_price = mm.midpoint_centered_fixed_spread(
                        ob, self.spread)
                    # TODO : improve by doing everything based on ohlcv since last check...

                    bid_volume, ask_volume = mm.simple_position_responsive_sizing(
                        self.base_volume,
                        self.position,
                    )
                    self.logger.info("balance: " +
                                     str(self.primary_exchange.get_balance()))
                    self.logger.info("bid volume: " + str(bid_volume) +
                                     " price: " + str(bid_price))
                    self.logger.info("ask volume: " + str(ask_volume) +
                                     " price: " + str(ask_price))

                    placeable_bid = self.primary_exchange.get_balance().get(
                        bid_price.currency
                    ).amount >= bid_price.amount * bid_volume.amount
                    placeable_ask = self.primary_exchange.get_balance().get(
                        ask_volume.currency).amount >= ask_volume.amount

                    # TODO : maybe we do not need to cancel everything everytime ?
                    self.primary_exchange.cancel_all_open_orders()

                    # Place order only if we can...
                    if placeable_bid:
                        self.primary_exchange.limit_order(
                            Consts.BID, bid_volume, bid_price)

                    # Place order only if we can...
                    if placeable_ask:
                        self.primary_exchange.limit_order(
                            Consts.ASK, ask_volume, ask_price)

                    self.last_bid_price = bid_price
                    self.last_ask_price = ask_price