Release v1.0.2
This commit is contained in:
@@ -0,0 +1,218 @@
|
||||
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
|
||||
Reference in New Issue
Block a user