def test_enact_order(create_exchange): # Create a trade exchange = copy.copy(create_exchange) exchange.reset() trade_price = exchange.current_price(symbol="ETH") trade_1 = Trade(0, "ETH", TradeType.LIMIT_BUY, 100, trade_price) exchange._next_observation() exchange.execute_trade(trade_1) trade_2 = Trade(1, "ETH", TradeType.LIMIT_BUY, 100, trade_price) exchange._next_observation() exchange.execute_trade(trade_2) trade_price = exchange.current_price(symbol="ETH") trade_3 = Trade(2, "ETH", TradeType.LIMIT_SELL, 73, trade_price) exchange._next_observation() exchange.execute_trade(trade_3) trade_4 = Trade(3, "ETH", TradeType.LIMIT_SELL, 50, trade_price) exchange._next_observation() exchange.execute_trade(trade_4) trade_5 = Trade(4, "ETH", TradeType.LIMIT_SELL, 25, trade_price) exchange._next_observation() exchange.execute_trade(trade_5) # Check that we're 5 trades in. assert len(exchange.trades) == 5 assert exchange._current_step == 5
def test_reward_invalid_trade_type_input(self): scheme = SimpleProfit() scheme.reset() # Create the first trade trade_1 = Trade(0, "BTC", 1, 100, 1500) trade_2 = Trade(2, "BTC", TradeType.LIMIT_SELL, 100, 1300) scheme.get_reward(0, trade_1) reward1 = scheme.get_reward(2, trade_2) assert reward1 == -1015.5908812273915
def test_raise_reward(self): scheme = SimpleProfit() scheme.reset() # Create the first trade trade_1 = Trade(0, "BTC", TradeType.LIMIT_BUY, 100, 1000) trade_2 = Trade(2, "BTC", TradeType.LIMIT_SELL, 100, 1500) scheme.get_reward(0, trade_1) reward1 = scheme.get_reward(2, trade_2) assert reward1 == 1926.0370135765718
def get_trade(self, current_step: int, action: TradeActionUnion) -> Trade: """The trade type is determined by `action % len(TradeType)`, and the trade amount is determined by the multiplicity of the action. For example, 1 = LIMIT_BUY|0.25, 2 = MARKET_BUY|0.25, 6 = LIMIT_BUY|0.5, 7 = MARKET_BUY|0.5, etc. """ n_splits = self.n_actions / len(TradeType) trade_type = TradeType(action % len(TradeType)) trade_amount = int(action / len(TradeType)) * float(1 / n_splits) + ( 1 / n_splits) current_price = self._exchange.current_price(symbol=self._instrument) base_precision = self._exchange.base_precision instrument_precision = self._exchange.instrument_precision amount = self._exchange.instrument_balance(self._instrument) price = current_price if trade_type is TradeType.MARKET_BUY or trade_type is TradeType.LIMIT_BUY: price_adjustment = 1 + (self.max_allowed_slippage_percent / 100) price = max( round(current_price * price_adjustment, base_precision), base_precision) amount = round( self._exchange.balance * 0.99 * trade_amount / price, instrument_precision) elif trade_type is TradeType.MARKET_SELL or trade_type is TradeType.LIMIT_SELL: price_adjustment = 1 - (self.max_allowed_slippage_percent / 100) price = round(current_price * price_adjustment, base_precision) amount_held = self._exchange.portfolio.get(self._instrument, 0) amount = round(amount_held * trade_amount, instrument_precision) return Trade(current_step, self._instrument, trade_type, amount, price)
def get_trade(self, action: TradeActionUnion) -> Trade: """ The trade type is determined by `action`, when there are only three types of trades: hold, buy and sell, implied by FutureTradeType. 将action转化成position和trade """ size = (self.action_space.n -1)/2 position = (action - size) / size ''' 比如说n = 5, 生成01234五种动作,实际上对应的持仓大小应该是-1 -0.5 0 0.5 1 ''' change = position - self.last_position if change > 0.001: trade_type = FutureTradeType.BUY elif change < -0.001: trade_type = FutureTradeType.SELL else: trade_type = FutureTradeType.HOLD amount = abs(change) price = self._exchange.current_price(symbol=self.instrument_symbol) next_price = self._exchange.next_price(symbol=self.instrument_symbol) self.last_position = position return Trade(self.instrument_symbol, trade_type, amount, price, next_price)
def fill_order(self, trade: Trade, current_price: float) -> Trade: amount_slippage = np.random.uniform( 0, self.max_amount_slippage_percent / 100) price_slippage = np.random.uniform( 0, self.max_price_slippage_percent / 100) fill_amount = trade.amount * (1 - amount_slippage) fill_price = current_price if trade.trade_type is TradeType.MARKET_BUY: fill_price = current_price * (1 + price_slippage) elif trade.trade_type is TradeType.LIMIT_BUY: fill_price = max(current_price * (1 + price_slippage), 1e-3) if fill_price > trade.price: fill_price = trade.price fill_amount *= trade.price / fill_price elif trade.trade_type is TradeType.MARKET_SELL: fill_price = current_price * (1 - price_slippage) elif trade.trade_type is TradeType.LIMIT_SELL: fill_price = max(current_price * (1 - price_slippage), 1e-3) if fill_price < trade.price: fill_price = trade.price fill_amount *= fill_price / trade.price return Trade(trade.step, trade.symbol, trade.trade_type, amount=fill_amount, price=fill_price)
def _execute_sell_order(self, order: 'Order', base_wallet: 'Wallet', quote_wallet: 'Wallet', current_price: float) -> Trade: price = self._contain_price(current_price) if order.type == TradeType.LIMIT and order.price > current_price: return None commission = Quantity(order.pair.base, order.size * self._commission, order.path_id) size = self._contain_size(order.size - commission.size) quantity = Quantity(order.pair.base, size, order.path_id) trade = Trade(order_id=order.id, exchange_id=self.id, step=self.clock.step, pair=order.pair, side=TradeSide.SELL, trade_type=order.type, quantity=quantity, price=price, commission=commission) # self._slippage_model.adjust_trade(trade) quote_size = trade.size / trade.price * (trade.price / order.price) quote_wallet -= Quantity(order.pair.quote, quote_size, order.path_id) base_wallet += quantity base_wallet -= commission return trade
def execute_trade(self, trade: Trade) -> Trade: if trade.trade_type == TradeType.LIMIT_BUY: order = self._exchange.create_limit_buy_order(symbol=trade.symbol, amount=trade.amount, price=trade.price) elif trade.trade_type == TradeType.MARKET_BUY: order = self._exchange.create_market_buy_order(symbol=trade.symbol, amount=trade.amount) elif trade.trade_type == TradeType.LIMIT_SELL: order = self._exchange.create_limit_sell_order(symbol=trade.symbol, amount=trade.amount, price=trade.price) elif trade.trade_type == TradeType.MARKET_SELL: order = self._exchange.create_market_sell_order( symbol=trade.symbol, amount=trade.amount) max_wait_time = time.time() + self._max_trade_wait_in_sec while order['status'] is 'open' and time.time() < max_wait_time: order = self._exchange.fetch_order(order.id) if order['status'] is 'open': self._exchange.cancel_order(order.id) self._performance.append( { 'balance': self.balance, 'net_worth': self.net_worth, }, ignore_index=True) return Trade(symbol=trade.symbol, trade_type=trade.trade_type, amount=order['filled'], price=order['price'])
def get_trade(self, action: TradeActionUnion) -> Trade: action_type, trade_amount = action trade_type = TradeType(int(action_type * len(TradeType))) current_price = self._exchange.current_price( symbol=self.instrument_symbol) base_precision = self._exchange.base_precision instrument_precision = self._exchange.instrument_precision amount = self._exchange.instrument_balance(self.instrument_symbol) price = current_price if trade_type is TradeType.MARKET_BUY or trade_type is TradeType.LIMIT_BUY: price_adjustment = 1 + (self.max_allowed_slippage_percent / 100) price = max( round(current_price * price_adjustment, base_precision), base_precision) amount = round( self._exchange.balance * 0.99 * trade_amount / price, instrument_precision) elif trade_type is TradeType.MARKET_SELL or trade_type is TradeType.LIMIT_SELL: price_adjustment = 1 - (self.max_allowed_slippage_percent / 100) price = round(current_price * price_adjustment, base_precision) amount_held = self._exchange.portfolio.get(self.instrument_symbol, 0) amount = round(amount_held * trade_amount, instrument_precision) return Trade(self.instrument_symbol, trade_type, amount, price)
def get_trade(self, current_step: int, action: TradeActionUnion) -> Trade: """The trade type is determined by `action % len(TradeType)`, and the trade amount is determined by the multiplicity of the action. 获取Trade对象,交易类型,由 action % len(TradeType)决定, 交易数量, 根据action 动作对应级别获取 For example, 1 = LIMIT_BUY|0.25, 2 = MARKET_BUY|0.25, 6 = LIMIT_BUY|0.5, 7 = MARKET_BUY|0.5, etc. """ # 每个交易动作,对应的操作仓位份数。 20/ 5 = 4 n_splits = self.n_actions / len(TradeType) # 交易类型 0 ~4 % 5 trade_type = TradeType(action % len(TradeType)) # 交易仓位, action/len(TradeType) +1 => 交易数量份数( 1~5) => 乘以每一份 trade_amount_percent = int(action / len(TradeType)) * float( 1 / n_splits) + (1 / n_splits) # 当前交易合约价格 current_price = self._exchange.current_price(symbol=self._instrument) # 基准合约价格精度 base_precision = self._exchange.base_precision # 交易合约价格精度 instrument_precision = self._exchange.instrument_precision # 当前合约持仓数量 amount = self._exchange.instrument_balance(self._instrument) # 当前价格 price = current_price # 市价/限价买入 if trade_type is TradeType.MARKET_BUY or trade_type is TradeType.LIMIT_BUY: # 滑点调整=》价格 price_adjustment = 1 + (self.max_allowed_slippage_percent / 100) # 精度修正=》价格 price = max( round(current_price * price_adjustment, base_precision), base_precision) # 账号基准净值 * 仓位比例 / 价格 =》 修正 =》 买入交易合约数量 amount = round( self._exchange.balance * 0.99 * trade_amount_percent / price, instrument_precision) # 市价卖出/限价卖出 elif trade_type is TradeType.MARKET_SELL or trade_type is TradeType.LIMIT_SELL: # 滑点调整=》价格 price_adjustment = 1 - (self.max_allowed_slippage_percent / 100) # 精度修正=》价格 price = round(current_price * price_adjustment, base_precision) # 交易合约当前持仓数量 amount_held = self._exchange.portfolio.get(self._instrument, 0) # 持仓数量 * 仓位比例 => 修正 =》 卖出交易合约数量 amount = round(amount_held * trade_amount_percent, instrument_precision) # 交易合约,交易类型,交易数量,交易价格 =》 Trade 对象 return Trade(current_step, self._instrument, trade_type, amount, price)
def test_slippage_trade(): """ Make sure the slippage is not zero. """ trade_2 = Trade(2, "BTC", TradeType.LIMIT_SELL, 100, 1300) slippage = RandomUniformSlippageModel(max_amount_slippage_percent=3.0) slipped_trade = slippage.fill_order(trade_2, 1300) # print(slipped_trade._price, slipped_trade._amount) assert slipped_trade.symbol == "BTC" assert slipped_trade.trade_type == TradeType.LIMIT_SELL assert slipped_trade.amount != trade_2.amount
def reset(self) -> pd.DataFrame: """Resets the state of the environment and returns an initial observation. Returns: observation: the initial observation. """ self._action_strategy.reset() self._reward_strategy.reset() self._exchange.reset() self._current_step = 0 return self._next_observation(Trade('N/A', 'hold', 0, 0))
def get_trade(self, current_step: int, action: TradeActionUnion) -> Trade: """ get a new Trade object. 根据action参数,获取一个新的Trade对象 :param action: 交易动作类型,(tuple) :return: """ # 动作类型(int), 交易仓位(0~1) action_type, trade_amount_percent = action # 交易类型 trade_type = TradeType(int(action_type * len(TradeType))) # 获取合约的当前价格 current_price = self._exchange.current_price(symbol=self._instrument) # 获取基准合约价格精度(例如USDT) base_precision = self._exchange.base_precision # 获取交易合约价格精度(例如BTC) instrument_precision = self._exchange.instrument_precision # 当前持有的 # 获取交易合约当前持仓数量 amount = self._exchange.instrument_balance(self._instrument) price = current_price # 市价买入/限价买入 if trade_type is TradeType.MARKET_BUY or trade_type is TradeType.LIMIT_BUY: # 滑点调整=》价格 price_adjustment = 1 + (self.max_allowed_slippage_percent / 100) # 精度修正=》价格 price = max( round(current_price * price_adjustment, base_precision), base_precision) # 账号基准净值 * 仓位比例 / 价格 =》 修正 =》 买入交易合约数量 amount = round( self._exchange.balance * 0.99 * trade_amount_percent / price, instrument_precision) # 市价卖出/限价卖出 elif trade_type is TradeType.MARKET_SELL or trade_type is TradeType.LIMIT_SELL: # 滑点调整=》价格 price_adjustment = 1 - (self.max_allowed_slippage_percent / 100) # 精度修正=》价格 price = round(current_price * price_adjustment, base_precision) # 交易合约当前持仓数量 amount_held = self._exchange.portfolio.get(self._instrument, 0) # 持仓数量 * 仓位比例 => 修正 =》 卖出交易合约数量 amount = round(amount_held * trade_amount_percent, instrument_precision) # 交易合约,交易类型,交易数量,交易价格 =》 Trade 对象 return Trade(current_step, self._instrument, trade_type, amount, price)
def get_trade(self, action: TradeActionUnion) -> Trade: """ The trade type is determined by `action`, when there are only three types of trades: hold, buy and sell, implied by FutureTradeType. ACTION is determined, by default, discrete(3), and it should only include (0,1,2) """ trade_type = FutureTradeType(action) amount = 0.1 current_price = self._exchange.current_price( symbol=self.instrument_symbol) price = current_price return Trade(self.instrument_symbol, trade_type, amount, price)
def fill_order(self, trade: Trade) -> Trade: fill_amount = trade.amount * ( 1 - np.random.uniform(0, self.max_amount_slippage_percent)) fill_price = trade.price if trade.trade_type is TradeType.MARKET_BUY or trade.trade_type is TradeType.LIMIT_BUY: fill_price = trade.price * ( 1 + np.random.uniform(0, self.max_price_slippage_percent)) elif trade.trade_type is TradeType.MARKET_SELL or trade.trade_type is TradeType.LIMIT_SELL: fill_price = trade.price * ( 1 - np.random.uniform(0, self.max_price_slippage_percent)) return Trade(trade.symbol, trade.trade_type, amount=fill_amount, price=fill_price)
def get_trade(self, current_step: int, action: TradeActionUnion) -> Trade: """The trade type is determined by `action % len(TradeType)`, and the trade amount is determined by the multiplicity of the action. For example, 1 = LIMIT_BUY|0.25, 2 = MARKET_BUY|0.25, 6 = LIMIT_BUY|0.5, 7 = MARKET_BUY|0.5, etc. """ # n_splits = self.n_actions / len(TradeType) # trade_type = TradeType(action % len(TradeType)) # trade_amount = int(action / len(TradeType)) * float(1 / n_splits) + (1 / n_splits) if action == 3: amount = abs(self._exchange.total_position) if self._exchange.total_position > 0: trade_type = TradeType(2) else: trade_type = TradeType(1) else: trade_type = TradeType(action) amount = self.max_allowed_amount current_price = self._exchange.current_price(symbol=self._instrument) # base_precision = self._exchange.base_precision # instrument_precision = self._exchange.instrument_precision # amount = self._exchange.instrument_balance(self._instrument) price = current_price # # if trade_type is TradeType.MARKET_BUY or trade_type is TradeType.LIMIT_BUY: # if trade_type is TradeType.MARKET_LONG: # price_adjustment = 1 + (self.max_allowed_slippage_percent / 100) # price = max(round(current_price * price_adjustment, base_precision), base_precision) # # amount = round(self._exchange.balance * 0.99 * trade_amount / price, instrument_precision) # # amount = round((self._exchange.balance * self._exchange.leverage * price) / 10000) + 5 # # amount = self.max_allowed_amount # # print('Position Size => ', amount, ' USDT') # # elif trade_type is TradeType.MARKET_SELL or trade_type is TradeType.LIMIT_SELL: # elif trade_type is TradeType.MARKET_SHORT: # price_adjustment = 1 - (self.max_allowed_slippage_percent / 100) # price = round(current_price * price_adjustment, base_precision) # amount_held = self._exchange.portfolio.get(self._instrument, 0) # # amount = round(amount_held * trade_amount, instrument_precision) # # amount = round((self._exchange.balance * self._exchange.leverage * price) / 10000) + 5 # # amount = self.max_allowed_amount # # print('Position Size => ', amount, ' USDT') return Trade(current_step, self._instrument, trade_type, amount, price)
def get_trade(self, action: TradeActionUnion) -> Trade: """The trade type is determined by `action % len(TradeType)`, and the trade amount is determined by the multiplicity of the action. For example: 0 = HOLD 1 = LIMIT_BUY|0.25 2 = MARKET_BUY|0.25 5 = HOLD 6 = LIMIT_BUY|0.5 7 = MARKET_BUY|0.5 etc. """ product_idx = int(action / self._actions_per_instrument) product = self._products[product_idx] n_splits = int(self._actions_per_instrument / len(TradeType)) trade_type = TradeType(action % len(TradeType)) trade_amount = int(action / len(TradeType)) * \ float(1 / n_splits) + (1 / n_splits) trade_amount = trade_amount - product_idx current_price = self._exchange.current_price(symbol=product) base_precision = self._exchange.base_precision instrument_precision = self._exchange.instrument_precision amount = self._exchange.instrument_balance(product) price = current_price if trade_type is TradeType.MARKET_BUY or trade_type is TradeType.LIMIT_BUY: price_adjustment = 1 + (self._max_allowed_slippage_percent / 100) price = max( round(current_price * price_adjustment, base_precision), base_precision) amount = round( self._exchange.balance * 0.99 * trade_amount / price, instrument_precision) elif trade_type is TradeType.MARKET_SELL or trade_type is TradeType.LIMIT_SELL: price_adjustment = 1 - (self._max_allowed_slippage_percent / 100) price = round(current_price * price_adjustment, base_precision) amount_held = self._exchange.portfolio.get(product, 0) amount = round(amount_held * trade_amount, instrument_precision) return Trade(product, trade_type, amount, price)
def _execute_buy_order(self, order: 'Order', base_wallet: 'Wallet', quote_wallet: 'Wallet', current_price: float) -> Trade: price = self._contain_price(current_price) if order.type == TradeType.LIMIT and order.price < current_price: return None commission = Quantity(order.pair.base, order.size * self._commission, order.path_id) base_size = self._contain_size(order.size - commission.size) if order.type == TradeType.MARKET: scale = order.price / price base_size = self._contain_size(scale * order.size - commission.size) base_wallet -= commission try: quantity = Quantity(order.pair.base, base_size, order.path_id) base_wallet -= quantity except InsufficientFundsForAllocation: balance = base_wallet.locked[order.path_id] quantity = Quantity(order.pair.base, balance.size, order.path_id) base_wallet -= quantity quote_size = (order.price / price) * (quantity.size / price) quote_wallet += Quantity(order.pair.quote, quote_size, order.path_id) trade = Trade(order_id=order.id, exchange_id=self.id, step=self.clock.step, pair=order.pair, side=TradeSide.BUY, trade_type=order.type, quantity=quantity, price=price, commission=commission) # self._slippage_model.adjust_trade(trade) return trade
def execute_buy_order(order: 'Order', base_wallet: 'Wallet', quote_wallet: 'Wallet', current_price: float, options: 'ExchangeOptions', exchange_id: str, clock: 'Clock') -> 'Trade': price = contain_price(current_price, options) if order.type == TradeType.LIMIT and order.price.rate < current_price: return None commission = Quantity(order.pair.base, order.size * options.commission, order.path_id) size = contain_size(order.size - commission.size, options) if order.type == TradeType.MARKET: scale = order.price.rate / price print(scale * order.size - commission.size) size = contain_size(scale * order.size - commission.size, options) base_wallet -= commission try: quantity = Quantity(order.pair.base, size, order.path_id) base_wallet -= quantity except InsufficientFunds: balance = base_wallet.locked[order.path_id] quantity = Quantity(order.pair.base, balance.size, order.path_id) base_wallet -= quantity quote_size = (order.price.rate / price) * (size / price) quote_wallet += Quantity(order.pair.quote, quote_size, order.path_id) trade = Trade(order_id=order.id, exchange_id=exchange_id, step=clock.step, pair=order.pair, side=TradeSide.BUY, trade_type=order.type, quantity=quantity, price=price, commission=commission) return trade
def get_trade(self, current_step: int, action: TradeActionUnion) -> Trade: if abs(float(action)) > 0.8: amount = abs(self._exchange.total_position) if self._exchange.total_position > 0: trade_type = TradeType(2) else: trade_type = TradeType(1) else: amount = self.max_allowed_amount if np.sign(action) > 0: trade_type = TradeType(1) elif np.sign(action) < 0: trade_type = TradeType(2) else: trade_type = TradeType(0) current_price = self._exchange.current_price(symbol=self._instrument) # base_precision = self._exchange.base_precision price = current_price # amount = self._exchange.instrument_balance(self._instrument) # if trade_type is TradeType.MARKET_LONG: # price_adjustment = 1 + (self.max_allowed_slippage_percent / 100) # price = max(round(current_price * price_adjustment, base_precision), base_precision) # # amount = round(self._exchange.balance * 0.99 * # # trade_amount / price, instrument_precision) # # amount = round(trade_amount * self.max_allowed_amount, instrument_precision) # # amount = round(trade_amount * (self._exchange.balance * self._exchange.leverage * price) * self.max_allowed_amount_percent / 100, instrument_precision) # # elif trade_type is TradeType.MARKET_SHORT: # price_adjustment = 1 - (self.max_allowed_slippage_percent / 100) # price = round(current_price * price_adjustment, base_precision) # # amount_held = self._exchange.portfolio.get(self._instrument, 0) # # amount = round(amount_held * trade_amount, instrument_precision) # # amount = round(trade_amount * self.max_allowed_amount, instrument_precision) # # amount = round(trade_amount * (self._exchange.balance * self._exchange.leverage * price) * self.max_allowed_amount_percent / 100, instrument_precision) return Trade(current_step, self._instrument, trade_type, amount, price)
def get_trade(self, action: TradeActionUnion) -> Trade: """The trade type is determined by `action % len(TradeType)`, and the trade amount is determined by the multiplicity of the action. For example, 1 = LIMIT_BUY|0.25, 2 = MARKET_BUY|0.25, 6 = LIMIT_BUY|0.5, 7 = MARKET_BUY|0.5, etc. """ #print('action is' + str(action)) n_splits = self.n_actions / len(TradeType) #4 = 20 / 5 trade_type = TradeType(action % len(TradeType)) #action 除以 TradeType 的 余数? action = 10 trade_amount = int(action / len(TradeType)) * float(1 / n_splits) + ( 1 / n_splits) #int(10 / 5) * (1/4) + (1/4) = 0.75 #这个应该是指买入的percent? current_price = self._exchange.current_price( symbol=self.instrument_symbol) base_precision = self._exchange.base_precision instrument_precision = self._exchange.instrument_precision amount = self._exchange.instrument_balance(self.instrument_symbol) #现在持有的量 price = current_price if trade_type is TradeType.MARKET_BUY or trade_type is TradeType.LIMIT_BUY: price_adjustment = 1 + (self.max_allowed_slippage_percent / 100) price = max( round(current_price * price_adjustment, base_precision), base_precision) amount = round( self._exchange.balance * 0.99 * trade_amount / price, instrument_precision) #99%的balance * 0.75 / 价格, 意思就是交易量是75%的现金 elif trade_type is TradeType.MARKET_SELL or trade_type is TradeType.LIMIT_SELL: price_adjustment = 1 - (self.max_allowed_slippage_percent / 100) price = round(current_price * price_adjustment, base_precision) amount_held = self._exchange.portfolio.get(self.instrument_symbol, 0) amount = round(amount_held * trade_amount, instrument_precision) return Trade(self.instrument_symbol, trade_type, amount, price)
def execute_order(self, order: 'Order', portfolio: 'Portfolio'): if order.type == TradeType.LIMIT and order.side == TradeSide.BUY: executed_order = self._exchange.create_limit_buy_order( order.symbol, order.size, order.price) elif order.type == TradeType.MARKET and order.side == TradeSide.BUY: executed_order = self._exchange.create_market_buy_order( order.symbol, order.size) elif order.type == TradeType.LIMIT and order.side == TradeSide.SELL: executed_order = self._exchange.create_limit_sell_order( order.symbol, order.size, order.price) elif order.type == TradeType.MARKET and order.side == TradeSide.SELL: executed_order = self._exchange.create_market_sell_order( order.symbol, order.size) else: return order.copy() max_wait_time = time.time() + self._max_trade_wait_in_sec while order['status'] == 'open' and time.time() < max_wait_time: executed_order = self._exchange.fetch_order(order.id) if order['status'] == 'open': self._exchange.cancel_order(order.id) order.cancel(self._exchange) trade = Trade(order_id=order.id, exchange_id=self.id, step=order.step, pair=order.pair, side=order.side, trade_type=order.type, quantity=executed_order['filled'] * order.pair.base, price=executed_order['price'], commission=executed_order['commission'] * order.pair.base) order.fill(self, trade)
def get_trade(self, action: TradeActionUnion) -> Trade: trade_type = TradeType(action % len(TradeType)) trade_amount = float(1 / (action % self.n_bins + 1)) current_price = self._exchange.current_price(symbol=self.asset_symbol) base_precision = self._exchange.base_precision asset_precision = self._exchange.asset_precision amount = 0 price = current_price if trade_type is TradeType.MARKET_BUY or trade_type is TradeType.LIMIT_BUY: price_adjustment = 1 + (self.max_allowed_slippage_percent / 100) price = round(current_price * price_adjustment, base_precision) amount = round(self._exchange.balance * trade_amount / price, asset_precision) elif trade_type is TradeType.MARKET_SELL or trade_type is TradeType.LIMIT_SELL: price_adjustment = 1 - (self.max_allowed_slippage_percent / 100) price = round(current_price * price_adjustment, base_precision) amount_held = self._exchange.portfolio.get(self.asset_symbol, 0) amount = round(amount_held * trade_amount, asset_precision) return Trade(self.asset_symbol, trade_type, amount, price)