diff --git a/src/dexorder/final_ohlc.py b/src/dexorder/final_ohlc.py index 7255214..439a3a0 100644 --- a/src/dexorder/final_ohlc.py +++ b/src/dexorder/final_ohlc.py @@ -233,6 +233,7 @@ class OHLCFileSeries: self.symbol = symbol self.series_start: Optional[datetime] = None # timestamp of the first datum in the series self.write_offset: Optional[int] = None + self.start_time_bytes: Optional[bytes] = None # if populated, these bytes are written at the start of the line on flush() self.last_flush: Optional[tuple[datetime,dec]] = None self.quote_file = None self.dirty_files = set() @@ -245,31 +246,7 @@ class OHLCFileSeries: def update(self, time: datetime, price: dec): - # - # load quote file - # - if self.quote_file is None: - quote_filename = self.quote_filename - try: - self.quote_file = open(quote_filename, 'br+') - # load existing quote file - line = self.quote_file.read().decode('ascii') - except FileNotFoundError: - os.makedirs(os.path.dirname(quote_filename), exist_ok=True) - self.quote_file = open(quote_filename, 'bw') - line = None - if line: - start, old_time, old_price = line.split(',') - self.series_start = from_timestamp(int(start)) - # position the write cursor at the start of the second column so we can write the latest quote quickly - self.write_offset = len(start) + 1 # after the start time bytes and comma - self.quote_file.seek(self.write_offset) - self.last_flush = from_timestamp(int(old_time)), dec(old_price) - else: - # initialize new quote file with our own series_start time - self.quote_file.write((str(timestamp(time)) + ',').encode('ascii')) - self.write_offset = 0 - self.last_flush = None + self._load(time) # # forward-fill OHLC files that would otherwise be empty/skipped @@ -295,6 +272,39 @@ class OHLCFileSeries: file.update(time, price) self.dirty_files.add(file) + + def _load(self, time): + # + # load quote file + # + if self.quote_file is None: + quote_filename = self.quote_filename + try: + self.quote_file = open(quote_filename, 'br+') + # load existing quote file + line = self.quote_file.read().decode('ascii') + except FileNotFoundError: + os.makedirs(os.path.dirname(quote_filename), exist_ok=True) + self.quote_file = open(quote_filename, 'bw') + line = None + try: + start, old_time, old_price = line.split(',') + except ValueError: + line = None + if line: + # noinspection PyUnboundLocalVariable + self.series_start = from_timestamp(int(start)) + # position the write cursor at the start of the second column so we can write the latest quote quickly + self.write_offset = len(start) + 1 # after the start time bytes and comma + self.quote_file.seek(self.write_offset) + # noinspection PyUnboundLocalVariable + self.last_flush = from_timestamp(int(old_time)), dec(old_price) + else: + # initialize new quote file with our own series_start time + self.start_time_bytes = f'{timestamp(time)},'.encode('ascii') + self.write_offset = 0 + self.last_flush = None + def flush(self): if self.quote is None: log.warning('OHLCFileSeries was flushed without having any updated data.') @@ -314,12 +324,16 @@ class OHLCFileSeries: # try: start_of_column = self.quote_file.tell() + if self.start_time_bytes: + self.quote_file.write(self.start_time_bytes) + self.start_time_bytes = None self.quote_file.write(f'{ts},{price:f}\n'.encode('ascii')) self.quote_file.truncate() self.quote_file.flush() self.quote_file.seek(start_of_column) except IOError: log.exception(f'While saving quote file {self.quote_filename}') + raise # remember the last flush point so we can forward-fill next time self.last_flush = self.quote