94 lines
3.3 KiB
Python
94 lines
3.3 KiB
Python
|
|
"""Tests for main.py integration with metrics system."""
|
||
|
|
|
||
|
|
import sys
|
||
|
|
import sqlite3
|
||
|
|
import tempfile
|
||
|
|
from pathlib import Path
|
||
|
|
from unittest.mock import patch, MagicMock
|
||
|
|
|
||
|
|
sys.path.append(str(Path(__file__).resolve().parents[1]))
|
||
|
|
|
||
|
|
# Mock typer to avoid import issues in tests
|
||
|
|
sys.modules['typer'] = MagicMock()
|
||
|
|
|
||
|
|
from storage import Storage
|
||
|
|
from strategies import DefaultStrategy
|
||
|
|
|
||
|
|
|
||
|
|
def test_strategy_database_integration():
|
||
|
|
"""Test that strategy gets database path set correctly in main workflow."""
|
||
|
|
with tempfile.NamedTemporaryFile(suffix=".db", delete=False) as tmp_file:
|
||
|
|
db_path = Path(tmp_file.name)
|
||
|
|
|
||
|
|
try:
|
||
|
|
# Create minimal test database
|
||
|
|
with sqlite3.connect(str(db_path)) as conn:
|
||
|
|
conn.execute("""
|
||
|
|
CREATE TABLE book (
|
||
|
|
id INTEGER PRIMARY KEY,
|
||
|
|
bids TEXT NOT NULL,
|
||
|
|
asks TEXT NOT NULL,
|
||
|
|
timestamp INTEGER NOT NULL
|
||
|
|
)
|
||
|
|
""")
|
||
|
|
conn.execute("""
|
||
|
|
CREATE TABLE trades (
|
||
|
|
id INTEGER PRIMARY KEY,
|
||
|
|
trade_id REAL NOT NULL,
|
||
|
|
price REAL NOT NULL,
|
||
|
|
size REAL NOT NULL,
|
||
|
|
side TEXT NOT NULL,
|
||
|
|
timestamp INTEGER NOT NULL
|
||
|
|
)
|
||
|
|
""")
|
||
|
|
|
||
|
|
# Insert minimal test data
|
||
|
|
bids = "[(50000.0, 10.0, 0, 1)]"
|
||
|
|
asks = "[(50001.0, 5.0, 0, 1)]"
|
||
|
|
conn.execute("INSERT INTO book (id, bids, asks, timestamp) VALUES (?, ?, ?, ?)",
|
||
|
|
(1, bids, asks, 1000))
|
||
|
|
conn.execute("INSERT INTO trades (id, trade_id, price, size, side, timestamp) VALUES (?, ?, ?, ?, ?, ?)",
|
||
|
|
(1, 1.0, 50000.0, 3.0, "buy", 1000))
|
||
|
|
conn.commit()
|
||
|
|
|
||
|
|
# Test the integration workflow
|
||
|
|
storage = Storage("BTC-USDT")
|
||
|
|
strategy = DefaultStrategy("BTC-USDT")
|
||
|
|
|
||
|
|
# This simulates the main.py workflow
|
||
|
|
strategy.set_db_path(db_path) # This is what main.py now does
|
||
|
|
storage.build_booktick_from_db(db_path, None) # This calculates and stores metrics
|
||
|
|
|
||
|
|
# Verify strategy can access stored metrics
|
||
|
|
assert strategy._db_path == db_path
|
||
|
|
|
||
|
|
# Verify metrics were stored by attempting to load them
|
||
|
|
metrics = strategy.load_stored_metrics(1000, 1000)
|
||
|
|
assert len(metrics) == 1
|
||
|
|
assert metrics[0].timestamp == 1000
|
||
|
|
|
||
|
|
# Verify strategy can be called (this is what main.py does)
|
||
|
|
strategy.on_booktick(storage.book) # Should use stored metrics
|
||
|
|
|
||
|
|
finally:
|
||
|
|
db_path.unlink(missing_ok=True)
|
||
|
|
|
||
|
|
|
||
|
|
def test_strategy_backwards_compatibility():
|
||
|
|
"""Test that strategy still works without database path (backwards compatibility)."""
|
||
|
|
storage = Storage("BTC-USDT")
|
||
|
|
strategy = DefaultStrategy("BTC-USDT")
|
||
|
|
|
||
|
|
# Don't set database path - should fall back to real-time calculation
|
||
|
|
# This ensures existing code that doesn't use metrics still works
|
||
|
|
|
||
|
|
# Create empty book
|
||
|
|
assert len(storage.book.snapshots) == 0
|
||
|
|
|
||
|
|
# Strategy should handle this gracefully
|
||
|
|
strategy.on_booktick(storage.book) # Should not crash
|
||
|
|
|
||
|
|
# Verify OBI calculation still works
|
||
|
|
obi_values = strategy.compute_OBI(storage.book)
|
||
|
|
assert obi_values == [] # Empty book should return empty list
|