def get_no_of_shares(self, capital: float, pct_risk_per_trade: float, volume_limit: float, price: Series, slippage: int = None, is_slip_up: bool = True) -> int: if not AppConsts.PRICE_COL_OPEN in price.index \ or not AppConsts.CUSTOM_COL_ADV in price.index: return 0 open_price: float = price.loc[AppConsts.PRICE_COL_OPEN] if slippage: if is_slip_up: open_price = NumberUtils.round(open_price + ( open_price * AppConsts.BASIS_POINT * slippage)) else: open_price = NumberUtils.round(open_price - ( open_price * AppConsts.BASIS_POINT * slippage)) no_of_shares: int = NumberUtils.to_floor(capital * pct_risk_per_trade / 100 / open_price) adv: float = price.loc[AppConsts.CUSTOM_COL_ADV] if price.loc[ AppConsts.CUSTOM_COL_ADV] > 0 else price.loc[ AppConsts.PRICE_COL_VOLUME] max_volume: float = NumberUtils.to_int(adv * volume_limit / 100) if no_of_shares > max_volume: LogUtils.warning( 'Capping max_volume adv={0}, no_of_shares={1}, max_volume={2}'. format(adv, no_of_shares, max_volume)) no_of_shares = max_volume return no_of_shares
def get_all_suggestions(self) -> int: error: Exception = None try: accnt: Account = self.get_account() capital: float = NumberUtils.to_floor( NumberUtils.to_float(accnt._raw['buying_power']) / 2) # 2 to trade everyday # Double Bottoms req: TradeSuggestionsRequest = TradeSuggestionsRequest() req.is_job = True req.current_capital = capital req.pct_risk_per_trade = 2.5 req.volume_limit = 0.01 req.test_limit_symbol = 800 req.adv_min = AppConsts.ADV_MIN_DFLT req.adpv_min = AppConsts.ADPV_MIN_DFLT req.strategy_type = AppConsts.STRATEGY_DOUBLE_BOTTOMS req.strategy_request = {} req.strategy_request['exponential_smoothing_alpha'] = 0.8 req.strategy_request['exponential_smoothing_max_min_diff'] = 0.7 req.strategy_request['double_bottoms_diff'] = 1 LogUtils.debug(StringUtils.to_json(req)) self.get_suggestions(req) # Double Tops req: TradeSuggestionsRequest = TradeSuggestionsRequest() req.is_job = True req.current_capital = capital req.pct_risk_per_trade = 2.5 req.volume_limit = 0.01 req.test_limit_symbol = 800 req.adv_min = AppConsts.ADV_MIN_DFLT req.adpv_min = AppConsts.ADPV_MIN_DFLT req.strategy_type = AppConsts.STRATEGY_DOUBLE_TOPS req.strategy_request = {} req.strategy_request['exponential_smoothing_alpha'] = 0.8 req.strategy_request['exponential_smoothing_max_min_diff'] = 0.7 req.strategy_request['double_tops_diff'] = 1 LogUtils.debug(StringUtils.to_json(req)) self.get_suggestions(req) except Exception as ex: error = ex finally: self.__email_client.send_html( subject=AppConsts.EMAIL_SUBJECT_GET_SUGGESTIONS, template_path=AppConsts.TEMPLATE_PATH_GET_SUGGESTIONS, model={'errors': [error] if error else []}) if error: LogUtils.error('Get Suggestions Error', error) 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