def init_history_watch(self, func: Callable[[StockItem, AlertItem], bool]) -> None: db_ref = fs_db.get_fs_db() def on_snapshot(col_snapshot, changes, read_time): for doc in col_snapshot: history_info = doc.to_dict() stock_item = StockItem( price=history_info['price'], price_day_low=history_info['day_low'], price_day_high=history_info['day_high'], symbol=history_info['symbol']) alerts = self.find_matching_alerts(stock_item) for alert in alerts: alert_info = alert.to_dict() print(f'Found alert: {alert_info}') alert_item = AlertItem( timestamp=alert_info['timestamp'], channel_id=alert_info['channel_id'], low=alert_info['low'], high=alert_info['high'], symbol=alert_info['symbol'], note=alert_info['note']) if not func(stock_item, alert_item): print('func fall failed, not deleting alert') return print(f'Deleting {alert.id}') db_ref.collection(u'alerts').document(alert.id).delete() self.history_watch = (db_ref.collection(u'history') .order_by(u'timestamp', direction=firestore.Query.DESCENDING) .limit(1) .on_snapshot(on_snapshot))
def add_stock_alert(self, discord_user: DiscordUser, timestamp: float, channel_id: int, symbol: str, low: int, high: int, note: str) -> None: """ Adds an alert for symbol. :param discord_user: The alert setter user :param timestamp: message's timestamp :param channel_id: message's channelId :param symbol: stock symbol to track :param low: lower boundry for alert to trigger :param high: upper boundry for alert to trigger :param note: note to print when alert triggers """ db_ref = fs_db.get_fs_db() db_ref.collection(u'alerts').add( { u'user_id': discord_user.name + discord_user.discriminator, u'timestamp': timestamp, u'channel_id': channel_id, u'symbol': symbol, u'low': low, u'high': high, u'note': note } )
def get_all_tracking_symbols(self) -> List[str]: """ :return: a list of all tracking symbols """ db_ref = fs_db.get_fs_db() docs = db_ref.collection(u'tracking').stream() out = [] for d in docs: d = d.to_dict() out.append(d[u'symbol']) return out
def add_stock_track(self, symbol: str) -> None: """ Add stock to track for finance bot. :param symbol: stock symbol """ db_ref = fs_db.get_fs_db() db_ref.collection(u'tracking').add( { u'symbol': symbol, } )
def add_stock_entry(self, timestamp: int, item: StockItem) -> None: """ Add stock entry to history table :param item: stock item """ db_ref = fs_db.get_fs_db() db_ref.collection(u'history').add( { u'timestamp': timestamp, u'symbol': item.symbol, u'day_low': item.price_day_low, u'day_high': item.price_day_high, u'price': item.price } )
def find_matching_alerts(self, item: StockItem) -> List[Any]: """ Alert if stock is less than low or more than high :param item: _description_ :return: _description_ """ db_ref = fs_db.get_fs_db() out: Any = [] alert_ref = (db_ref.collection(u'alerts') .where(u'symbol', u'==', item.symbol) .where(u'low', u'>', item.price)) out.extend(doc for doc in alert_ref.stream()) alert_ref = (db_ref.collection(u'alerts') .where(u'symbol', u'==', item.symbol) .where(u'high', u'<', item.price)) out.extend(doc for doc in alert_ref.stream()) return out
def get_stock_history(self, symbols: List[str], from_ts: float) -> Dict[str, StatItem]: """ Gets history for all stock symbols :param symbol: _description_ :return: _description_ """ db_ref = fs_db.get_fs_db() out = {} for sym in symbols: item = StatItem() hist_ref = ( db_ref.collection(u'history') .where(u'timestamp', u'>=', from_ts) .where(u'symbol', u'==', sym)) for entry in hist_ref.stream(): info = entry.to_dict() item.timestamps.append(int(info['timestamp'])/(3600*24)) item.values.append(int(info['price'])) out[sym] = item return out