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'))
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'))
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'))
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