text: from __future__ import annotations
  from typing import List
  
  from ros.core.moment import Moment
  from ros.core.series import DaySeries
  from ros.core.stock import Stock
  from ros.util.conversion.datetime import IntuitiveDateConverter
  
  
  class SymbolDayRegister:
  
      def __init__(self):
          self.series = dict()
  
      def add_moment(self, moment: Moment):
          """
          Add a single moment. Re-establish chronological date order.
          """
  
          stock = moment.get_stock()
          if stock not in self.series:
              self.series[stock] = DaySeries()
  
          self.series[stock].add_moment(moment)
  
      def add_moments(self, moments: List[Moment]):
          """
          Add a list of moments. Re-establish chronological date order.
          """
  
          pre_sorted = dict()
  
          for moment in moments:
              stock = moment.get_stock()
              if stock not in pre_sorted:
                  pre_sorted[stock] = list()
              pre_sorted[stock].append(moment)
  
          for stock, stock_moments in pre_sorted.items():
              if stock not in self.series:
                  self.series[stock] = DaySeries()
              self.series[stock].add_moments(stock_moments)
  
      def get(self, stock: Stock, day: str, offset=0) -> Moment:
          """
          Retrieve a moment by stock and date.
          """
          epoch_s = IntuitiveDateConverter.to_epoch_s(day)
  
          if offset == 0:
              return self.series[stock].get(epoch_s)
  
          _series = self.series.get(stock, None)
          if _series is None:
              return None
  
          if epoch_s not in _series.timestamps:
              return None
  
          _ix = _series.timestamps.index(epoch_s)
          _ix += offset
          if _ix < 0:
              return None
          if _ix >= len(_series.timestamps):
              return None
          return _series.get(_series.timestamps[_ix])
  
      def get_close(self, stock: Stock, epoch_s: float, offset: int=0) -> float:
          """
          Retrieve close price by symbol and date.
          """
          moment = self.get(stock, epoch_s, offset)
          if moment is None:
              return None
          return moment.close
  
      def get_all_timestamps(self) -> List[float]:
          """
          Return sorted list of all timestamps in the register.
          """
  
          all_timestamps = list()
          for stock in self.series.keys():
              all_timestamps += self.series[stock].timestamps
          all_timestamps = list(set(all_timestamps))
          all_timestamps.sort()
  
          return all_timestamps
  
      def get_timestamps_for_stock(self, stock: Stock) -> List[float]:
  
          if stock not in self.series.keys():
              return list()
  
          series = self.series[stock]
          return series.timestamps
  
      def keys(self):
          """
          Return all symbol keys of this register.
          """
          return self.series.keys()
  
      def stocks_available(self, epoch_s: float) -> List[Stock]:
          """
          Return a list of stocks that are available to trade on the given epoch.
          """
  
          available = list()
          stocks = self.keys()
          for stock in stocks:
              if self.get_close(stock, epoch_s, 0) is not None:
                  available.append(stock)
  
          return available
  
      def get_all_moments(self) -> List[Moment]:
          """
          Return a list of all moments in the register.
          """
  
          moments = list()
          for stock in self.keys():
              series = self.series[stock]
              moments += series.get_moments()
          return moments
  
      def merge(self, other_register: SymbolDayRegister):
          """
          Take in moments of other register.
          """
  
          moments = other_register.get_all_moments()
          self.add_moments(moments)
  
      def subset(self, stocks: List[Stock]) -> SymbolDayRegister:
          """
          Return a subset register of the selected stocks.
          """
  
          subset_series = dict()
          for stock in stocks:
              if stock in self.series.keys():
                  subset_series[stock] = self.series[stock]
  
          subset_register = SymbolDayRegister()
          subset_register.series = subset_series
          return subset_register
  