def execute_sell_order(order: 'Order', base_wallet: 'Wallet', quote_wallet: 'Wallet', current_price: float, options: 'ExchangeOptions', clock: 'Clock') -> 'Trade': if order.type == TradeType.LIMIT and order.price > current_price: return None filled = order.remaining.contain(order.exchange_pair) commission = options.commission * filled quantity = filled - commission if commission.size < Decimal(10)**-quantity.instrument.precision: order.cancel("COMMISSION IS LESS THAN PRECISION.") return None # Transfer Funds from Quote Wallet to Base Wallet transfer = Wallet.transfer(source=quote_wallet, target=base_wallet, quantity=quantity, commission=commission, exchange_pair=order.exchange_pair, reason="SELL") trade = Trade(order_id=order.id, step=clock.step, exchange_pair=order.exchange_pair, side=TradeSide.SELL, trade_type=order.type, quantity=transfer.quantity, price=transfer.price, commission=transfer.commission) return trade
def adjust_trade(self, trade: Trade) -> Trade: price_slippage = np.random.uniform(0, self.max_slippage_percent / 100) initial_price = trade.price if trade.type == TradeType.MARKET: if trade.side == TradeSide.BUY: trade.price = max(initial_price * (1 + price_slippage), 1e-3) else: trade.price = max(initial_price * (1 - price_slippage), 1e-3) else: if trade.side == TradeSide.BUY: trade.price = max(initial_price * (1 + price_slippage), 1e-3) if trade.price > initial_price: trade.size *= min(initial_price / trade.price, 1) else: trade.price = max(initial_price * (1 - price_slippage), 1e-3) if trade.price < initial_price: trade.size *= min(trade.price / initial_price, 1) 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 < 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 / price size = contain_size(scale * order.size - commission.size, options) base_wallet -= commission.reason("COMMISSION FOR BUY") try: quantity = Quantity(order.pair.base, size, order.path_id) base_wallet -= quantity.reason("REMOVE FROM LOCKED TO FILL ORDER") except InsufficientFunds: balance = base_wallet.locked[order.path_id] quantity = Quantity(order.pair.base, balance.size, order.path_id) base_wallet -= quantity.reason( "REMOVE FROM LOCKED TO FILL ORDER (INSUFFICIENT FUNDS)") quote_size = (order.price / price) * (size / price) filled_quantity = Quantity(order.pair.quote, quote_size, order.path_id) quote_wallet += filled_quantity.reason("BOUGHT @ {} {}".format( price, order.pair)) 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 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 < 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 / price 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 / 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 execute_buy_order(order: 'Order', base_wallet: 'Wallet', quote_wallet: 'Wallet', current_price: float, options: 'ExchangeOptions', clock: 'Clock') -> 'Trade': if order.type == TradeType.LIMIT and order.price < current_price: return None filled = order.remaining.contain(order.exchange_pair) if order.type == TradeType.MARKET: scale = order.price / max(current_price, order.price) filled = scale * filled commission = options.commission * filled quantity = filled - commission if commission.size < Decimal(10)**-quantity.instrument.precision: order.cancel("COMMISSION IS LESS THAN PRECISION.") return None transfer = Wallet.transfer(source=base_wallet, target=quote_wallet, quantity=quantity, commission=commission, exchange_pair=order.exchange_pair, reason="BUY") trade = Trade(order_id=order.id, step=clock.step, exchange_pair=order.exchange_pair, side=TradeSide.BUY, trade_type=order.type, quantity=transfer.quantity, price=transfer.price, commission=transfer.commission) return trade