def sync_orders(self) -> int: errors: List[Exception] = [] try: req: GetTradeOrdersRequest = GetTradeOrdersRequest() req.status = [ AppConsts.ORDER_STATUS_SUBMITTED_ENTRY, AppConsts.ORDER_STATUS_SUBMITTED_EXIT ] orders: List[TradeOrderCustom] = self.get_trade_orders(req) if not orders: LogUtils.debug('No orders submitted') for order in orders: try: LogUtils.debug('Sync order for = {0}'.format( order.symbol_master.symbol)) resp: Order = None if order.trade_order.status == AppConsts.ORDER_STATUS_SUBMITTED_ENTRY: resp = self.__alpaca_client.get_order( order.trade_order.alpaca_id) elif order.trade_order.status == AppConsts.ORDER_STATUS_SUBMITTED_EXIT: resp = self.__alpaca_client.get_order( order.trade_order.exit_alpaca_id) if resp: org: TradeOrder = BaseService._get_by_id( TradeOrder, order.trade_order.id) if not org: raise NotFoundException('TradeOrder', 'id', order.trade_order.id) if order.trade_order.status == AppConsts.ORDER_STATUS_SUBMITTED_ENTRY \ and resp.status == AppConsts.ALPACA_ORDER_STATUS_FILLED: org.status = AppConsts.ORDER_STATUS_IN_POSITION org.actual_qty = NumberUtils.to_int( resp.filled_qty) org.actual_entry_price = NumberUtils.to_float( resp.filled_avg_price) org.modified = datetime.now() BaseService._update() elif order.trade_order.status == AppConsts.ORDER_STATUS_SUBMITTED_ENTRY \ and resp.status == AppConsts.ALPACA_ORDER_STATUS_CANCELLED: org.status = AppConsts.ORDER_STATUS_CANCELLED_ENTRY org.modified = datetime.now() BaseService._update() elif order.trade_order.status == AppConsts.ORDER_STATUS_SUBMITTED_EXIT \ and resp.status == AppConsts.ALPACA_ORDER_STATUS_FILLED: exit_price: StockPriceDaily = self.__stock_service.get_single_stock_price_daily( order.symbol_master.id, DateUtils.get_date( datetime.today().strftime('%Y-%m-%d'), '%Y-%m-%d')) if exit_price: org.exit_stock_price_daily_id = exit_price.id org.status = AppConsts.ORDER_STATUS_COMPLETED org.actual_exit_price = NumberUtils.to_float( resp.filled_avg_price) org.modified = datetime.now() BaseService._update() elif order.trade_order.status == AppConsts.ORDER_STATUS_SUBMITTED_EXIT \ and resp.status == AppConsts.ALPACA_ORDER_STATUS_CANCELLED: org.status = AppConsts.ORDER_STATUS_CANCELLED_EXIT org.modified = datetime.now() BaseService._update() raise Exception('Exit Error = {0}'.format( resp.status)) else: raise Exception('Sync Status = {0}'.format( resp.status)) else: raise NotFoundException('Alpaca Order', 'id', order.trade_order.alpaca_id) except Exception as ex: LogUtils.error('Sync Orders Error', ex) errors.append(ex) except Exception as ex: LogUtils.error('Sync Orders Error', ex) errors.append(ex) finally: self.__email_client.send_html( subject=AppConsts.EMAIL_SUBJECT_SYNC_ORDERS, template_path=AppConsts.TEMPLATE_PATH_SYNC_ORDERS, model={'errors': errors}) return 1
def close_positions(self) -> int: errors: List[Exception] = [] try: is_tmrw_valid: bool = self.__alpaca_client.is_tmrw_valid() if not is_tmrw_valid: LogUtils.warning('Tmrw is not a valid trade date') raise BadRequestException('Date', DateUtils.to_string(date.today())) req: GetTradeOrdersRequest = GetTradeOrdersRequest() req.exact_status = AppConsts.ORDER_STATUS_IN_POSITION orders: List[TradeOrderCustom] = self.get_trade_orders(req) if not orders: LogUtils.debug('No positions') for order in orders: try: LogUtils.debug('Check position for = {0}'.format( order.symbol_master.symbol)) spd: StockPriceDaily = self.__stock_service.get_last_single_stock_price_daily( order.symbol_master.id) if not spd: LogUtils.warning('No Stock Price Found') raise NotFoundException('SPD', 'symbol_id', order.symbol_master.id) LogUtils.debug('Last close price = {0}'.format( spd.close_price)) # is_exit: bool = (spd.close_price > order.trade_order.target_price # or spd.close_price < order.trade_order.stop_loss) if True: # To-do: fix this to use strategy service. is_exit: LogUtils.debug('Close position for = {0}'.format( order.symbol_master.symbol)) resp: Order = self.__alpaca_client.submit_order( symbol=order.symbol_master.symbol, qty=order.trade_order.actual_qty, action=AppConsts.ACTION_SELL if order.trade_order.action == AppConsts.ACTION_BUY else AppConsts.ACTION_BUY) if resp: org: TradeOrder = BaseService._get_by_id( TradeOrder, order.trade_order.id) if not org: LogUtils.warning('Order not found.') raise NotFoundException( 'TradeOrder', 'id', order.trade_order.id) org.exit_alpaca_id = resp.id org.status = AppConsts.ORDER_STATUS_SUBMITTED_EXIT org.modified = datetime.now() BaseService._update() else: raise Exception('Close Position Error.') except Exception as ex: LogUtils.error('Close Position Error', ex) errors.append(ex) except Exception as ex: LogUtils.error('Close Position Error', ex) errors.append(ex) finally: self.__email_client.send_html( subject=AppConsts.EMAIL_SUBJECT_CLOSE_POSITIONS, template_path=AppConsts.TEMPLATE_PATH_CLOSE_POSITIONS, model={'errors': errors}) return 1
def queue_positions(self) -> int: errors: List[Exception] = [] try: is_tmrw_valid: bool = self.__alpaca_client.is_tmrw_valid() if not is_tmrw_valid: LogUtils.warning('Tmrw is not a valid trade date') raise BadRequestException('Date', DateUtils.to_string(date.today())) req: GetTradeOrdersRequest = GetTradeOrdersRequest() # If Sunday, check Friday's price. today: date = date.today() if today.weekday() == AppConsts.WEEKDAY_IDX_SUN: today = DateUtils.add_business_days(today, -1) req.created = today.strftime('%Y-%m-%d') req.exact_status = AppConsts.ORDER_STATUS_INIT orders: List[TradeOrderCustom] = self.get_trade_orders(req) req_to_ignore: GetTradeOrdersRequest = GetTradeOrdersRequest() req_to_ignore.status = [ AppConsts.ORDER_STATUS_SUBMITTED_ENTRY, AppConsts.ORDER_STATUS_IN_POSITION, AppConsts.ORDER_STATUS_SUBMITTED_EXIT, AppConsts.ORDER_STATUS_CANCELLED_EXIT ] orders_to_ignore: List[TradeOrderCustom] = self.get_trade_orders( req_to_ignore) symbols_to_ignore: List[str] = [ o.symbol_master.symbol for o in orders_to_ignore ] if orders_to_ignore else [] LogUtils.debug('symbols_to_ignore = {0}'.format(symbols_to_ignore)) if not orders: LogUtils.debug('No orders suggested') shuffle(orders) prioritized_orders: List[TradeOrderCustom] = [] for order in orders: if order.trade_order.strategy == AppConsts.STRATEGY_DOUBLE_BOTTOMS: prioritized_orders.append(order) for order in orders: if order.trade_order.strategy == AppConsts.STRATEGY_DOUBLE_TOPS: prioritized_orders.append(order) accnt: Account = self.__alpaca_client.get_account() capital: float = NumberUtils.to_floor( NumberUtils.to_float(accnt._raw['buying_power']) / 2) # 2 to trade everyday for order in prioritized_orders: try: LogUtils.debug('Try symbol = {0}'.format( order.symbol_master.symbol)) if order.symbol_master.symbol in symbols_to_ignore: LogUtils.debug('Ignore for = {0}'.format( order.symbol_master.symbol)) continue cost: float = NumberUtils.to_float( order.stock_price_daily.close_price * order.trade_order.qty) if cost > capital: LogUtils.debug('Too expensive for = {0}'.format( order.symbol_master.symbol)) continue capital = capital - cost resp: Order = self.__alpaca_client.submit_order( symbol=order.symbol_master.symbol, qty=order.trade_order.qty, action=order.trade_order.action) if resp: org: TradeOrder = BaseService._get_by_id( TradeOrder, order.trade_order.id) if not org: raise NotFoundException('TradeOrder', 'id', order.trade_order.id) org.alpaca_id = resp.id org.status = AppConsts.ORDER_STATUS_SUBMITTED_ENTRY org.order_type = AppConsts.ORDER_TYPE_MARKET org.time_in_force = AppConsts.TIME_IN_FORCE_DAY org.modified = datetime.now() BaseService._update() except Exception as ex: LogUtils.error('Queue Position Error', ex) errors.append(ex) except Exception as ex: LogUtils.error('Queue Position Error', ex) errors.append(ex) finally: self.__email_client.send_html( subject=AppConsts.EMAIL_SUBJECT_QUEUE_POSITIONS, template_path=AppConsts.TEMPLATE_PATH_QUEUE_POSITIONS, model={'errors': errors}) return 1