final ohlc bugfix
This commit is contained in:
@@ -233,6 +233,7 @@ class OHLCFileSeries:
|
|||||||
self.symbol = symbol
|
self.symbol = symbol
|
||||||
self.series_start: Optional[datetime] = None # timestamp of the first datum in the series
|
self.series_start: Optional[datetime] = None # timestamp of the first datum in the series
|
||||||
self.write_offset: Optional[int] = None
|
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.last_flush: Optional[tuple[datetime,dec]] = None
|
||||||
self.quote_file = None
|
self.quote_file = None
|
||||||
self.dirty_files = set()
|
self.dirty_files = set()
|
||||||
@@ -245,31 +246,7 @@ class OHLCFileSeries:
|
|||||||
|
|
||||||
|
|
||||||
def update(self, time: datetime, price: dec):
|
def update(self, time: datetime, price: dec):
|
||||||
#
|
self._load(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
|
|
||||||
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
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# forward-fill OHLC files that would otherwise be empty/skipped
|
# forward-fill OHLC files that would otherwise be empty/skipped
|
||||||
@@ -295,6 +272,39 @@ class OHLCFileSeries:
|
|||||||
file.update(time, price)
|
file.update(time, price)
|
||||||
self.dirty_files.add(file)
|
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):
|
def flush(self):
|
||||||
if self.quote is None:
|
if self.quote is None:
|
||||||
log.warning('OHLCFileSeries was flushed without having any updated data.')
|
log.warning('OHLCFileSeries was flushed without having any updated data.')
|
||||||
@@ -314,12 +324,16 @@ class OHLCFileSeries:
|
|||||||
#
|
#
|
||||||
try:
|
try:
|
||||||
start_of_column = self.quote_file.tell()
|
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.write(f'{ts},{price:f}\n'.encode('ascii'))
|
||||||
self.quote_file.truncate()
|
self.quote_file.truncate()
|
||||||
self.quote_file.flush()
|
self.quote_file.flush()
|
||||||
self.quote_file.seek(start_of_column)
|
self.quote_file.seek(start_of_column)
|
||||||
except IOError:
|
except IOError:
|
||||||
log.exception(f'While saving quote file {self.quote_filename}')
|
log.exception(f'While saving quote file {self.quote_filename}')
|
||||||
|
raise
|
||||||
|
|
||||||
# remember the last flush point so we can forward-fill next time
|
# remember the last flush point so we can forward-fill next time
|
||||||
self.last_flush = self.quote
|
self.last_flush = self.quote
|
||||||
|
|||||||
Reference in New Issue
Block a user