Source code for analysis_engine.build_buy_order

"""
Helper for creating a buy order
"""

import analysis_engine.consts as ae_consts
import analysis_engine.utils as ae_utils
import spylunking.log.setup_logging as log_utils

log = log_utils.build_colorized_logger(name=__name__)


[docs]def build_buy_order( ticker, num_owned, close, balance, commission, date, details, use_key, minute=None, shares=None, version=1, auto_fill=True, is_live_trading=False, backtest_shares_default=10, reason=None): """build_buy_order Create an algorithm buy order as a dictionary .. note:: setting the ``minute`` is required to build a minute-by-minute ``Trading History`` :param ticker: ticker :param num_owned: integer current owned number of shares for this asset :param close: float closing price of the asset :param balance: float amount of available capital :param commission: float for commission costs :param date: string trade date for that row usually ``COMMON_DATE_FORMAT`` (``YYYY-MM-DD``) :param minute: optional - string with the minute that the order was placed. format is ``COMMON_TICK_DATE_FORMAT`` (``YYYY-MM-DD HH:MM:SS``) :param details: dictionary for full row of values to review all buys after the algorithm finishes. (usually ``row.to_json()``) :param use_key: string for redis and s3 publishing of the algorithm result dictionary as a json-serialized dictionary :param shares: optional - integer number of shares to buy if None buy max number of shares at the ``close`` with the available ``balance`` amount. :param version: optional - version tracking integer :param auto_fill: optional - bool for not assuming the trade filled (default ``True``) :param is_live_trading: optional - bool for filling trades for live trading or for backtest tuning filled (default ``False`` which is backtest mode) :param backtest_shares_default: optional - integer for simulating shares during a backtest even if there are not enough funds (default ``10``) :param reason: optional - string for recording why the algo decided to buy for review after the algorithm finishes """ status = ae_consts.TRADE_OPEN s3_bucket_name = ae_consts.ALGO_BUYS_S3_BUCKET_NAME s3_key = use_key redis_key = use_key s3_enabled = True redis_enabled = True cost_of_trade = None new_shares = num_owned new_balance = balance created_date = None tradable_funds = balance - (2.0 * commission) if not is_live_trading: if not shares: shares = backtest_shares_default tradable_funds = ( (shares * close) + (2.0 * commission)) if close > 0.1 and tradable_funds > 10.0: can_buy_num_shares = shares if not can_buy_num_shares: can_buy_num_shares = int(tradable_funds / close) cost_of_trade = ae_consts.to_f( val=(can_buy_num_shares * close) + commission) if can_buy_num_shares > 0: if cost_of_trade > balance: status = ae_consts.TRADE_NOT_ENOUGH_FUNDS else: created_date = ae_utils.utc_now_str() if auto_fill: new_shares = int(num_owned + can_buy_num_shares) new_balance = ae_consts.to_f(balance - cost_of_trade) status = ae_consts.TRADE_FILLED else: new_shares = shares new_balance = balance else: status = ae_consts.TRADE_NOT_ENOUGH_FUNDS else: status = ae_consts.TRADE_NOT_ENOUGH_FUNDS order_dict = { 'ticker': ticker, 'status': status, 'balance': new_balance, 'shares': new_shares, 'buy_price': cost_of_trade, 'prev_balance': balance, 'prev_shares': num_owned, 'close': close, 'details': details, 'reason': reason, 'date': date, 'minute': minute, 'created': created_date, 's3_bucket': s3_bucket_name, 's3_key': s3_key, 'redis_key': redis_key, 's3_enabled': s3_enabled, 'redis_enabled': redis_enabled, 'version': version } use_date = minute if not use_date: use_date = date log.debug( f'{ticker} {use_date} buy ' f'{ae_consts.get_status(status=order_dict["status"])} ' f'order={ae_consts.ppj(order_dict)}') return order_dict
# end of build_buy_order