Source code for tensortrade.oms.services.execution.simulated

import logging
from decimal import Decimal

from tensortrade.core import Clock
from tensortrade.oms.wallets import Wallet
from tensortrade.oms.exchanges import ExchangeOptions
from tensortrade.oms.orders import Order, Trade, TradeType, TradeSide

from typing import Union


[docs]def execute_buy_order(order: 'Order', base_wallet: 'Wallet', quote_wallet: 'Wallet', current_price: float, options: 'ExchangeOptions', clock: 'Clock') -> Union[None, 'Trade']: """Executes a buy order on the exchange. Parameters ---------- order : `Order` The order that is being filled. base_wallet : `Wallet` The wallet of the base instrument. quote_wallet : `Wallet` The wallet of the quote instrument. current_price : float The current price of the exchange pair. options : `ExchangeOptions` The exchange options. clock : `Clock` The clock for the trading process.. Returns ------- `Trade` The executed trade that was made. """ 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 # If the user has specified a non-zero commission percentage, it has to be higher # than the instrument precision, otherwise the minimum precision value is used. minimum_commission = Decimal(10) ** -filled.instrument.precision if options.commission > 0 and commission < minimum_commission: logging.warning("Commission is > 0 but less than instrument precision. " "Setting commission to the minimum allowed amount. " "Consider defining a custom instrument with a higher precision.") commission.size = minimum_commission quantity = filled - commission 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
[docs]def execute_sell_order(order: 'Order', base_wallet: 'Wallet', quote_wallet: 'Wallet', current_price: float, options: 'ExchangeOptions', clock: 'Clock') -> Union[None, 'Trade']: """Executes a sell order on the exchange. Parameters ---------- order : `Order` The order that is being filled. base_wallet : `Wallet` The wallet of the base instrument. quote_wallet : `Wallet` The wallet of the quote instrument. current_price : float The current price of the exchange pair. options : `ExchangeOptions` The exchange options. clock : `Clock` The clock for the trading process.. Returns ------- `Trade` The executed trade that was made. """ if order.type == TradeType.LIMIT and order.price > current_price: return None filled = order.remaining.contain(order.exchange_pair) commission = options.commission * filled # If the user has specified a non-zero commission percentage, it has to be higher # than the instrument precision, otherwise the minimum precision value is used. minimum_commission = Decimal(10) ** -filled.instrument.precision if options.commission > 0 and commission < minimum_commission: logging.warning("Commission is > 0 but less than instrument precision. " "Setting commission to the minimum allowed amount. " "Consider defining a custom instrument with a higher precision.") commission.size = minimum_commission quantity = filled - commission # 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
[docs]def execute_order(order: 'Order', base_wallet: 'Wallet', quote_wallet: 'Wallet', current_price: float, options: 'Options', clock: 'Clock') -> 'Trade': """Executes an order on the exchange. Parameters ---------- order : `Order` The order that is being filled. base_wallet : `Wallet` The wallet of the base instrument. quote_wallet : `Wallet` The wallet of the quote instrument. current_price : float The current price of the exchange pair. options : `ExchangeOptions` The exchange options. clock : `Clock` The clock for the trading process.. Returns ------- `Trade` The executed trade that was made. """ kwargs = {"order": order, "base_wallet": base_wallet, "quote_wallet": quote_wallet, "current_price": current_price, "options": options, "clock": clock} if order.is_buy: trade = execute_buy_order(**kwargs) elif order.is_sell: trade = execute_sell_order(**kwargs) else: trade = None return trade