async def _create_initial_arbitrage_order(self, arbitrage_container): current_symbol_holding, current_market_holding, market_quantity, price, symbol_market = \ await trading_personal_data.get_pre_order_data(self.exchange_manager, symbol=self.trading_mode.symbol, timeout=trading_constants.ORDER_DATA_FETCHING_TIMEOUT) created_orders = [] order_type = trading_enums.TraderOrderType.BUY_LIMIT if arbitrage_container.state is trading_enums.EvaluatorStates.LONG \ else trading_enums.TraderOrderType.SELL_LIMIT quantity = self._get_quantity_from_holdings(current_symbol_holding, market_quantity, arbitrage_container.state) if order_type is trading_enums.TraderOrderType.SELL_LIMIT: quantity = trading_personal_data.add_dusts_to_quantity_if_necessary( quantity, price, symbol_market, current_symbol_holding) for order_quantity, order_price in trading_personal_data.check_and_adapt_order_details_if_necessary( quantity, arbitrage_container.own_exchange_price, symbol_market): current_order = trading_personal_data.create_order_instance( trader=self.exchange_manager.trader, order_type=order_type, symbol=self.trading_mode.symbol, current_price=arbitrage_container.own_exchange_price, quantity=order_quantity, price=order_price) created_order = await self.exchange_manager.trader.create_order( current_order) created_orders.append(created_order) arbitrage_container.initial_limit_order_id = created_order.order_id self.open_arbitrages.append(arbitrage_container) # only create one order per arbitrage return created_orders
async def _create_secondary_arbitrage_order(self, arbitrage_container, quantity): created_orders = [] current_symbol_holding, current_market_holding, market_quantity, price, symbol_market = \ await trading_personal_data.get_pre_order_data(self.exchange_manager, symbol=self.trading_mode.symbol, timeout=trading_constants.ORDER_DATA_FETCHING_TIMEOUT) now_selling = arbitrage_container.state is trading_enums.EvaluatorStates.LONG if now_selling: quantity = trading_personal_data.add_dusts_to_quantity_if_necessary( quantity, price, symbol_market, current_symbol_holding) for order_quantity, order_price in trading_personal_data.check_and_adapt_order_details_if_necessary( quantity, arbitrage_container.target_price, symbol_market): current_order = trading_personal_data.create_order_instance( trader=self.exchange_manager.trader, order_type=trading_enums.TraderOrderType.SELL_LIMIT if now_selling else trading_enums.TraderOrderType.BUY_LIMIT, symbol=self.trading_mode.symbol, current_price=arbitrage_container.own_exchange_price, quantity=order_quantity, price=order_price) created_order = await self.exchange_manager.trader.create_order( current_order) created_orders.append(created_order) arbitrage_container.secondary_limit_order_id = created_order.order_id stop_price = self._get_stop_loss_price( symbol_market, arbitrage_container.own_exchange_price, now_selling) current_order = trading_personal_data.create_order_instance( trader=self.exchange_manager.trader, order_type=trading_enums.TraderOrderType.STOP_LOSS, symbol=self.trading_mode.symbol, current_price=arbitrage_container.own_exchange_price, quantity=order_quantity, price=stop_price, linked_to=created_order, side=trading_enums.TradeOrderSide.SELL if now_selling else trading_enums.TradeOrderSide.BUY) await self.exchange_manager.trader.create_order(current_order) arbitrage_container.secondary_stop_order_id = current_order.order_id return created_orders
async def create_new_orders(self, symbol, final_note, state, **kwargs): current_order = None timeout = kwargs.pop("timeout", trading_constants.ORDER_DATA_FETCHING_TIMEOUT) try: current_symbol_holding, current_market_holding, market_quantity, price, symbol_market = \ await trading_personal_data.get_pre_order_data(self.exchange_manager, symbol=symbol, timeout=timeout) quote, _ = symbol_util.split_symbol(symbol) created_orders = [] if state == trading_enums.EvaluatorStates.VERY_SHORT.value and not self.DISABLE_SELL_ORDERS: quantity = self._get_market_quantity_from_risk( final_note, current_symbol_holding, quote, True) quantity = trading_personal_data.add_dusts_to_quantity_if_necessary( quantity, price, symbol_market, current_symbol_holding) for order_quantity, order_price in self._check_and_adapt_order_details_if_necessary( quantity, price, symbol_market): current_order = trading_personal_data.create_order_instance( trader=self.trader, order_type=trading_enums.TraderOrderType.SELL_MARKET, symbol=symbol, current_price=float(order_price), quantity=float(order_quantity), price=float(order_price)) await self.trader.create_order(current_order) created_orders.append(current_order) elif state == trading_enums.EvaluatorStates.SHORT.value and not self.DISABLE_SELL_ORDERS: quantity = await self._get_sell_limit_quantity_from_risk( final_note, current_symbol_holding, quote) quantity = trading_personal_data.add_dusts_to_quantity_if_necessary( quantity, price, symbol_market, current_symbol_holding) limit_price = trading_personal_data.adapt_price( symbol_market, price * self._get_limit_price_from_risk(final_note)) for order_quantity, order_price in self._check_and_adapt_order_details_if_necessary( quantity, limit_price, symbol_market): current_order = trading_personal_data.create_order_instance( trader=self.trader, order_type=trading_enums.TraderOrderType.SELL_LIMIT, symbol=symbol, current_price=price, quantity=float(order_quantity), price=float(order_price)) updated_limit = await self.trader.create_order( current_order) created_orders.append(updated_limit) if self.USE_STOP_ORDERS: stop_price = trading_personal_data.adapt_price( symbol_market, price * self._get_stop_price_from_risk()) current_order = trading_personal_data.create_order_instance( trader=self.trader, order_type=trading_enums.TraderOrderType.STOP_LOSS, symbol=symbol, current_price=price, quantity=float(order_quantity), price=stop_price, linked_to=updated_limit) await self.trader.create_order(current_order) elif state == trading_enums.EvaluatorStates.NEUTRAL.value: return [] # TODO : stop loss elif state == trading_enums.EvaluatorStates.LONG.value and not self.DISABLE_BUY_ORDERS: quantity = self._get_buy_limit_quantity_from_risk( final_note, market_quantity, quote) quantity = quantity * await self._get_quantity_ratio(quote) limit_price = trading_personal_data.adapt_price( symbol_market, price * self._get_limit_price_from_risk(final_note)) for order_quantity, order_price in self._check_and_adapt_order_details_if_necessary( quantity, limit_price, symbol_market): current_order = trading_personal_data.create_order_instance( trader=self.trader, order_type=trading_enums.TraderOrderType.BUY_LIMIT, symbol=symbol, current_price=price, quantity=float(order_quantity), price=float(order_price)) await self.trader.create_order(current_order) created_orders.append(current_order) elif state == trading_enums.EvaluatorStates.VERY_LONG.value and not self.DISABLE_BUY_ORDERS: quantity = self._get_market_quantity_from_risk( final_note, market_quantity, quote) quantity = quantity * await self._get_quantity_ratio(quote) for order_quantity, order_price in self._check_and_adapt_order_details_if_necessary( quantity, price, symbol_market): current_order = trading_personal_data.create_order_instance( trader=self.trader, order_type=trading_enums.TraderOrderType.BUY_MARKET, symbol=symbol, current_price=float(order_price), quantity=float(order_quantity), price=float(order_price)) await self.trader.create_order(current_order) created_orders.append(current_order) if created_orders: return created_orders raise trading_errors.MissingMinimalExchangeTradeVolume() except (trading_errors.MissingFunds, trading_errors.MissingMinimalExchangeTradeVolume): raise except asyncio.TimeoutError as e: self.logger.error( f"Impossible to create order for {symbol} on {self.exchange_manager.exchange_name}: {e} " f"and is necessary to compute the order details.") return [] except Exception as e: self.logger.exception(e, True, f"Failed to create order : {e}.") return []
async def test_get_additional_dusts_to_quantity_if_necessary(): symbol_market = { Ecmsc.LIMITS.value: { Ecmsc.LIMITS_AMOUNT.value: { Ecmsc.LIMITS_AMOUNT_MIN.value: 0.5 }, Ecmsc.LIMITS_COST.value: { Ecmsc.LIMITS_COST_MIN.value: 1 } } } current_symbol_holding = 5 quantity = 3 price = 1 assert personal_data.add_dusts_to_quantity_if_necessary( quantity, price, symbol_market, current_symbol_holding) == quantity + 0 current_symbol_holding = 5 quantity = 4 price = 1 assert personal_data.add_dusts_to_quantity_if_necessary( quantity, price, symbol_market, current_symbol_holding) == quantity + 1 current_symbol_holding = 5 quantity = 4.5 price = 1 assert personal_data.add_dusts_to_quantity_if_necessary( quantity, price, symbol_market, current_symbol_holding) == quantity + 0.5 symbol_market = { Ecmsc.LIMITS.value: { Ecmsc.LIMITS_AMOUNT.value: { Ecmsc.LIMITS_AMOUNT_MIN.value: 0.005 }, Ecmsc.LIMITS_COST.value: { Ecmsc.LIMITS_COST_MIN.value: 0.00005 } } } current_symbol_holding = 0.99000000001 quantity = 0.9 price = 0.5 assert personal_data.add_dusts_to_quantity_if_necessary( quantity, price, symbol_market, current_symbol_holding) == quantity + 0 current_symbol_holding = 0.99000000001 quantity = 0.0215245845 price = 0.5 assert personal_data.add_dusts_to_quantity_if_necessary( quantity, price, symbol_market, current_symbol_holding) == quantity + 0 current_symbol_holding = 0.99999999 quantity = 0.99999 price = 0.5 assert personal_data.add_dusts_to_quantity_if_necessary( quantity, price, symbol_market, current_symbol_holding) == 0.99999999 current_symbol_holding = 0.88 quantity = 0.7055680057024826 price = 0.0002 assert personal_data.add_dusts_to_quantity_if_necessary( quantity, price, symbol_market, current_symbol_holding) == 0.88 # price = 0 => no dust assert personal_data.add_dusts_to_quantity_if_necessary( quantity, 0, symbol_market, current_symbol_holding) == quantity