219 lines
6.8 KiB
Python
219 lines
6.8 KiB
Python
import importlib.util
|
|
import sqlite3
|
|
from pathlib import Path
|
|
|
|
import pandas as pd
|
|
|
|
|
|
def load_panel_app_module():
|
|
module_path = Path("panel/spbt_day_panel.py").resolve()
|
|
spec = importlib.util.spec_from_file_location("spbt_day_panel_app", module_path)
|
|
module = importlib.util.module_from_spec(spec)
|
|
assert spec.loader is not None
|
|
spec.loader.exec_module(module)
|
|
return module
|
|
|
|
|
|
def create_panel_fixture_db(db_path: Path) -> None:
|
|
trading_day_start_ns = pd.Timestamp("2026-06-17T00:00:00Z").value
|
|
conn = sqlite3.connect(db_path)
|
|
try:
|
|
conn.execute(
|
|
"""
|
|
CREATE TABLE selector_pairs (
|
|
time_ns INTEGER,
|
|
tstamp TEXT,
|
|
pair_name TEXT,
|
|
instrument_a TEXT,
|
|
instrument_b TEXT,
|
|
mr_score TEXT
|
|
)
|
|
"""
|
|
)
|
|
conn.execute(
|
|
"""
|
|
CREATE TABLE trading_instructions (
|
|
time_ns INTEGER,
|
|
tstamp TEXT,
|
|
book_id TEXT,
|
|
strategy_id TEXT,
|
|
type TEXT,
|
|
data TEXT
|
|
)
|
|
"""
|
|
)
|
|
conn.execute(
|
|
"""
|
|
CREATE TABLE ohlcv_1min (
|
|
tstamp TEXT,
|
|
tstamp_ns INTEGER,
|
|
exch_acct TEXT,
|
|
exchange_id TEXT,
|
|
instrument_id TEXT,
|
|
interval_sec INTEGER,
|
|
open REAL,
|
|
high REAL,
|
|
low REAL,
|
|
close REAL,
|
|
volume REAL,
|
|
vwap REAL,
|
|
num_trades INTEGER
|
|
)
|
|
"""
|
|
)
|
|
conn.execute(
|
|
"INSERT INTO selector_pairs VALUES (?, ?, ?, ?, ?, ?)",
|
|
(
|
|
10,
|
|
"2026-06-17T00:00:00Z",
|
|
"AAA:USD-BBB:USD",
|
|
"EXCH:PAIR-AAA-USD",
|
|
"EXCH:PAIR-BBB-USD",
|
|
'{"final":"0.5"}',
|
|
),
|
|
)
|
|
conn.executemany(
|
|
"INSERT INTO trading_instructions VALUES (?, ?, ?, ?, ?, ?)",
|
|
[
|
|
(
|
|
trading_day_start_ns,
|
|
"2026-06-17T00:00:00Z",
|
|
"book",
|
|
"strategy-AAA:USD-BBB:USD",
|
|
"TARGET_POSITION",
|
|
(
|
|
'{"action":"TARGET","quote_asset":"USD","assets":'
|
|
'{"AAA":{"reference_price":"100","strength":"0.5"},'
|
|
'"BBB":{"reference_price":"50","strength":"-0.5"}}}'
|
|
),
|
|
),
|
|
(
|
|
trading_day_start_ns + 60_000_000_000,
|
|
"2026-06-17T00:01:00Z",
|
|
"book",
|
|
"strategy-AAA:USD-BBB:USD",
|
|
"CLOSE_POSITION",
|
|
(
|
|
'{"action":"CLOSE","quote_asset":"USD","assets":'
|
|
'{"AAA":{"reference_price":"110"},'
|
|
'"BBB":{"reference_price":"45"}}}'
|
|
),
|
|
),
|
|
],
|
|
)
|
|
conn.executemany(
|
|
"INSERT INTO ohlcv_1min VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
|
|
[
|
|
(
|
|
"2026-06-17T00:00:00Z",
|
|
trading_day_start_ns,
|
|
"EXCH",
|
|
"EXCH",
|
|
"PAIR-AAA-USD",
|
|
60,
|
|
100.0,
|
|
100.0,
|
|
100.0,
|
|
100.0,
|
|
1.0,
|
|
100.0,
|
|
1,
|
|
),
|
|
(
|
|
"2026-06-17T00:00:00Z",
|
|
trading_day_start_ns,
|
|
"EXCH",
|
|
"EXCH",
|
|
"PAIR-BBB-USD",
|
|
60,
|
|
50.0,
|
|
50.0,
|
|
50.0,
|
|
50.0,
|
|
1.0,
|
|
50.0,
|
|
1,
|
|
),
|
|
],
|
|
)
|
|
conn.commit()
|
|
finally:
|
|
conn.close()
|
|
|
|
|
|
def test_pair_analyze_grid_keeps_clean_labels_and_full_pair_values():
|
|
module = load_panel_app_module()
|
|
pair_theo_ret = pd.DataFrame(
|
|
{
|
|
"pair_name": ["BTC:USD-ETH:USD", "ADA:USD-BTC:USD"],
|
|
"mr_ranking": [2, 1],
|
|
"realized_pnl": [0.0, 0.0],
|
|
"unrealized_pnl": [0.0, 0.0],
|
|
}
|
|
)
|
|
|
|
formatted = module.spbt_day.format_pair_theo_ret_for_analyze_grid(pair_theo_ret)
|
|
|
|
assert formatted["pair_name"].tolist() == ["BTC-ETH", "ADA-BTC"]
|
|
assert formatted[module.spbt_day.PAIR_NAME_VALUE_COLUMN].tolist() == [
|
|
"BTC:USD-ETH:USD",
|
|
"ADA:USD-BTC:USD",
|
|
]
|
|
|
|
|
|
def test_panel_app_uses_fast_list_template(tmp_path):
|
|
module = load_panel_app_module()
|
|
app = module.SpbtDayPanelApp(repo_root=tmp_path)
|
|
view = app.view
|
|
|
|
assert isinstance(view, module.pn.template.FastListTemplate)
|
|
assert view.title == module.APP_TITLE
|
|
assert view.sidebar_width == 430
|
|
assert view.accent_base_color == module.APP_ACCENT_COLOR
|
|
assert view.header_background == module.APP_HEADER_COLOR
|
|
assert len(view.sidebar) == 1
|
|
assert len(view.main) == 1
|
|
|
|
|
|
def test_panel_app_calculates_pairs_and_selected_pair_outputs(tmp_path):
|
|
module = load_panel_app_module()
|
|
data_dir = tmp_path / "data"
|
|
data_dir.mkdir()
|
|
db_path = data_dir / "20260617.spbt_results.db"
|
|
create_panel_fixture_db(db_path)
|
|
|
|
app = module.SpbtDayPanelApp(repo_root=tmp_path)
|
|
app.directory_input.value = str(data_dir)
|
|
app.refresh_files()
|
|
app.min_pctg_change_input.value = 0.0
|
|
|
|
app.calculate()
|
|
|
|
assert app.file_select.value == str(db_path)
|
|
assert app.file_select.width == 360
|
|
assert app.min_pctg_change_input.width == 220
|
|
assert app.calculate_button.width == 110
|
|
assert app.total_pnl_histogram.sizing_mode == "stretch_width"
|
|
assert app.selected_pair_market_plot.sizing_mode == "stretch_width"
|
|
assert app.pair_theo_ret_table.pagination is None
|
|
assert app.pair_theo_ret_table.layout == "fit_data_table"
|
|
assert app.pair_theo_ret_table.value["pair_name"].tolist() == ["AAA-BBB"]
|
|
assert (
|
|
app.pair_theo_ret_table.value[module.spbt_day.PAIR_NAME_VALUE_COLUMN].tolist()
|
|
== ["AAA:USD-BBB:USD"]
|
|
)
|
|
assert app.selected_pair_name is None
|
|
assert app.selected_pair_executions_table.value.empty
|
|
assert app.selected_pair_market_plot.object is None
|
|
|
|
app.analyze_pair_row(0)
|
|
|
|
assert app.selected_pair_name == "AAA:USD-BBB:USD"
|
|
assert app.selected_pair_executions_table.value["action"].tolist() == [
|
|
"TARGET",
|
|
"TARGET",
|
|
"CLOSE",
|
|
"CLOSE",
|
|
]
|
|
assert app.selected_pair_market_plot.object is not None
|