67 lines
2.3 KiB
Python
67 lines
2.3 KiB
Python
|
|
"""Offline microbenchmarks; run with .venv/Scripts/python benchmarks/hotpaths.py."""
|
||
|
|
|
||
|
|
import sys
|
||
|
|
from datetime import datetime, time
|
||
|
|
from pathlib import Path
|
||
|
|
from statistics import median
|
||
|
|
from timeit import repeat
|
||
|
|
|
||
|
|
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
|
||
|
|
|
||
|
|
from libs.calc import trading_time
|
||
|
|
from sdk.models import _parse_datetime, _side
|
||
|
|
from strategy.trend.open import _parse_minutes
|
||
|
|
|
||
|
|
|
||
|
|
def original_date(date, clock):
|
||
|
|
clock = clock.replace(':', '').zfill(6)
|
||
|
|
try:
|
||
|
|
return datetime.strptime(date.replace('-', '') + clock, '%Y%m%d%H%M%S')
|
||
|
|
except ValueError:
|
||
|
|
return None
|
||
|
|
|
||
|
|
|
||
|
|
def original_minutes(value):
|
||
|
|
try:
|
||
|
|
hour_text, minute_text = value.strip().split(':')
|
||
|
|
hour, minute = int(hour_text), int(minute_text)
|
||
|
|
except (TypeError, ValueError):
|
||
|
|
return None
|
||
|
|
if not 0 <= hour <= 23 or not 0 <= minute <= 59:
|
||
|
|
return None
|
||
|
|
return hour * 60 + minute
|
||
|
|
|
||
|
|
|
||
|
|
def original_trading_time(now):
|
||
|
|
if now.weekday() >= 5:
|
||
|
|
return False
|
||
|
|
return time(9, 30) <= now.time() <= time(11, 30) or time(13) <= now.time() <= time(15)
|
||
|
|
|
||
|
|
|
||
|
|
def measure(name, before, after, number=10000):
|
||
|
|
assert before() == after(), name
|
||
|
|
old = median(repeat(before, number=number, repeat=5)) / number
|
||
|
|
new = median(repeat(after, number=number, repeat=5)) / number
|
||
|
|
print(f'{name:26} {old * 1e6:10.3f} -> {new * 1e6:10.3f} us {old / new:7.2f}x')
|
||
|
|
|
||
|
|
|
||
|
|
def main():
|
||
|
|
print(sys.version)
|
||
|
|
print('Same interpreter, original versus optimized; cache timings are warm.')
|
||
|
|
now = datetime(2026, 9, 7, 14)
|
||
|
|
measure('order date', lambda: original_date('20260907', '100000'),
|
||
|
|
lambda: _parse_datetime('20260907', '100000'))
|
||
|
|
measure('signal time bound', lambda: original_minutes('9:30'), lambda: _parse_minutes('9:30'))
|
||
|
|
measure('trading session', lambda: original_trading_time(now), lambda: trading_time(now))
|
||
|
|
measure('order side', lambda: {'23': 'BUY', '24': 'SELL', '48': 'BUY', '49': 'SELL'}.get(str(23), ''),
|
||
|
|
lambda: _side(23))
|
||
|
|
positions = {f'{i:06}.SH': None for i in range(1000)}
|
||
|
|
codes = list(positions)
|
||
|
|
signals = [f'{i:06}.SH' for i in range(500, 2500)]
|
||
|
|
measure('1000 positions/2000 signals', lambda: [c for c in signals if c not in codes],
|
||
|
|
lambda: [c for c in signals if c not in positions], number=100)
|
||
|
|
|
||
|
|
|
||
|
|
if __name__ == '__main__':
|
||
|
|
main()
|