Source code for pyqqq.backtest.wallclock

import asyncio
import datetime as dtm
from typing import Optional


[docs] class WallClock: """실시간 및 백테스팅 모드를 지원하는 시간 관리 클래스입니다. 이 클래스는 트레이딩 시스템에서 시간을 관리하는 핵심 컴포넌트로, 실시간 거래와 백테스팅에서 동일한 인터페이스를 제공합니다. 시간대(timezone) 관리와 시간 변경 이벤트 처리를 지원합니다. Example: .. highlight:: python .. code-block:: python # 실시간 모드 clock = WallClock(live_mode=True) current = clock.now() await clock.sleep(1) # 실제 1초 대기 # 백테스팅 모드 clock = WallClock( live_mode=False, start_time=datetime(2023, 1, 1), end_time=datetime(2023, 12, 31) ) while clock.is_alive(): current = clock.now() await clock.sleep(60) # 가상으로 1분 진행 """ live_mode: bool """ 실시간/백테스팅 모드 구분 """ tzinfo: Optional[dtm.tzinfo] """ 시간대 정보 """ current_time: Optional[dtm.datetime] """ 현재 시간 (백테스팅 모드에서만 사용) """ end_time: Optional[dtm.datetime] """ 종료 시간 (백테스팅 모드에서만 사용) """ on_time_change: Optional[callable] """ 시간 변경 후 호출될 콜백 함수 """ on_before_time_change: Optional[callable] """ 시간 변경 전 호출될 콜백 함수 """
[docs] def __init__(self, live_mode: bool = True, start_time: Optional[dtm.datetime] = None, end_time: Optional[dtm.datetime] = None, tzinfo: Optional[dtm.tzinfo] = None): """WallClock 클래스를 초기화합니다. Args: live_mode (bool, optional): 실시간/백테스팅 모드 구분. Defaults to True. start_time (Optional[datetime], optional): 백테스팅 시작 시간. Defaults to None. live_mode=False일 때만 사용. end_time (Optional[datetime], optional): 백테스팅 종료 시간. Defaults to None. live_mode=False일 때만 사용. tzinfo (Optional[datetime.tzinfo], optional): 시간대 정보. Defaults to None. """ self.live_mode = live_mode self.tzinfo = tzinfo if not live_mode: self.current_time = start_time self.end_time = end_time if end_time is not None else dtm.datetime.now() if self.tzinfo is not None: self.current_time = self.current_time.astimezone(self.tzinfo) self.end_time = self.end_time.astimezone(self.tzinfo) self.on_time_change = None self.on_before_time_change = None
[docs] def now(self) -> dtm.datetime: """현재 시간을 반환합니다. Returns: datetime: 현재 시간 - 실시간 모드: 실제 현재 시간 - 백테스팅 모드: 시뮬레이션 현재 시간 Raises: ValueError: 백테스팅 모드에서 현재 시간이 실제 시간보다 미래인 경우 """ if self.live_mode: return dtm.datetime.now(self.tzinfo) else: if self.current_time > dtm.datetime.now(self.tzinfo): raise ValueError("backtesting time is must be less than current time") return self.current_time
[docs] def today(self) -> dtm.date: """현재 날짜를 반환합니다. Returns: date: 현재 날짜 """ return self.now().date()
[docs] def is_alive(self) -> bool: """시계가 동작 중인지 확인합니다. Returns: bool: 시계 동작 여부 - 실시간 모드: 항상 True - 백테스팅 모드: 현재 시간이 종료 시간 이전이면 True """ if self.live_mode: return True else: return self.current_time <= self.end_time
[docs] async def sleep(self, seconds: float): """지정된 시간만큼 대기합니다. Args: seconds (float): 대기할 시간(초) Note: - 실시간 모드: asyncio.sleep을 사용하여 실제로 대기 - 백테스팅 모드: 가상 시간을 진행하고 콜백 함수 호출 1. on_before_time_change 콜백 호출 (설정된 경우) 2. 현재 시간 업데이트 3. on_time_change 콜백 호출 (설정된 경우) """ if self.live_mode: await asyncio.sleep(seconds) else: before = self.current_time after = before + dtm.timedelta(seconds=seconds) if self.on_before_time_change: self.on_before_time_change(before, after) self.current_time = after if self.on_time_change: self.on_time_change(self.current_time, before)