This commit is contained in:
Oleg Sheynin
2026-07-30 02:39:21 +00:00
parent f49a10f54e
commit 4ddf4017bd
41 changed files with 1570 additions and 13025 deletions
+150 -11
View File
@@ -148,7 +148,7 @@ def test_load_pair_market_data_maps_selector_instruments_and_relative_close():
)
conn.execute(
"""
CREATE TABLE ohlcv_1min (
CREATE TABLE market (
tstamp TEXT,
tstamp_ns INTEGER,
exch_acct TEXT,
@@ -166,7 +166,7 @@ def test_load_pair_market_data_maps_selector_instruments_and_relative_close():
),
)
conn.executemany(
"INSERT INTO ohlcv_1min VALUES (?, ?, ?, ?, ?)",
"INSERT INTO market VALUES (?, ?, ?, ?, ?)",
[
("pre", 9, "EXCH_A", "PAIR-AAA-USD", 90.0),
("t0", 10, "EXCH_A", "PAIR-AAA-USD", 100.0),
@@ -239,7 +239,7 @@ def test_load_pair_market_data_requires_market_rows_for_both_assets():
)
conn.execute(
"""
CREATE TABLE ohlcv_1min (
CREATE TABLE market (
tstamp TEXT,
tstamp_ns INTEGER,
exch_acct TEXT,
@@ -257,13 +257,13 @@ def test_load_pair_market_data_requires_market_rows_for_both_assets():
),
)
conn.execute(
"INSERT INTO ohlcv_1min VALUES (?, ?, ?, ?, ?)",
"INSERT INTO market VALUES (?, ?, ?, ?, ?)",
("t1", 1, "EXCH_A", "PAIR-AAA-USD", 100.0),
)
with pytest.raises(
ValueError,
match=r"ohlcv_1min does not contain market data for asset\(s\): BBB",
match=r"market does not contain data for asset\(s\): BBB",
):
load_pair_market_data(
conn,
@@ -286,7 +286,7 @@ def test_load_pair_market_data_requires_time_zero_close_for_each_asset():
)
conn.execute(
"""
CREATE TABLE ohlcv_1min (
CREATE TABLE market (
tstamp TEXT,
tstamp_ns INTEGER,
exch_acct TEXT,
@@ -304,7 +304,7 @@ def test_load_pair_market_data_requires_time_zero_close_for_each_asset():
),
)
conn.executemany(
"INSERT INTO ohlcv_1min VALUES (?, ?, ?, ?, ?)",
"INSERT INTO market VALUES (?, ?, ?, ?, ?)",
[
("t1", 1, "EXCH_A", "PAIR-AAA-USD", None),
("t2", 2, "EXCH_A", "PAIR-AAA-USD", 110.0),
@@ -314,7 +314,7 @@ def test_load_pair_market_data_requires_time_zero_close_for_each_asset():
with pytest.raises(
ValueError,
match=r"ohlcv_1min initial close must be positive for asset\(s\): AAA",
match=r"market initial close must be positive for asset\(s\): AAA",
):
load_pair_market_data(
conn,
@@ -337,7 +337,7 @@ def test_load_pair_market_data_requires_exact_trading_day_start_row():
)
conn.execute(
"""
CREATE TABLE ohlcv_1min (
CREATE TABLE market (
tstamp TEXT,
tstamp_ns INTEGER,
exch_acct TEXT,
@@ -355,7 +355,7 @@ def test_load_pair_market_data_requires_exact_trading_day_start_row():
),
)
conn.executemany(
"INSERT INTO ohlcv_1min VALUES (?, ?, ?, ?, ?)",
"INSERT INTO market VALUES (?, ?, ?, ?, ?)",
[
("t1", 11, "EXCH_A", "PAIR-AAA-USD", 110.0),
("t0", 10, "EXCH_B", "PAIR-BBB-USD", 50.0),
@@ -365,7 +365,7 @@ def test_load_pair_market_data_requires_exact_trading_day_start_row():
with pytest.raises(
ValueError,
match=(
"ohlcv_1min does not contain trading-day start close for "
"market does not contain trading-day start close for "
r"asset\(s\): AAA"
),
):
@@ -891,6 +891,143 @@ def test_load_trading_instructions_validates_required_table():
load_trading_instructions(conn)
def test_load_trading_instructions_requires_sp_quant_metric_columns():
conn = sqlite3.connect(":memory:")
conn.execute(
"""
CREATE TABLE trading_instructions (
tstamp TEXT,
tstamp_ns INTEGER,
action TEXT,
quote_asset TEXT,
assets TEXT
)
"""
)
with pytest.raises(
ValueError,
match=r"SP Quant column\(s\) \[beta, scaled_disequilibrium\]",
):
load_trading_instructions(conn)
def test_load_trading_instructions_reads_sp_quant_schema_with_time_alias():
conn = sqlite3.connect(":memory:")
conn.execute(
"""
CREATE TABLE trading_instructions (
tstamp TEXT,
tstamp_ns INTEGER,
type TEXT,
book_id TEXT,
strategy_id TEXT,
action TEXT,
quote_asset TEXT,
assets TEXT,
scaled_disequilibrium REAL,
beta REAL
)
"""
)
conn.executemany(
"INSERT INTO trading_instructions VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
[
(
"t2",
2,
"CLOSE_POSITION",
"book",
"strategy",
"CLOSE",
"USD",
'{"AAA":{"reference_price":"110"},"BBB":{"reference_price":"45"}}',
-0.5,
0.75,
),
(
"t1",
1,
"TARGET_POSITION",
"book",
"strategy",
"TARGET",
"USD",
(
'{"AAA":{"reference_price":"100","strength":"0.5"},'
'"BBB":{"reference_price":"50","strength":"-0.5"}}'
),
-1.25,
0.75,
),
],
)
trading_instructions = load_trading_instructions(conn)
assert trading_instructions["tstamp_ns"].tolist() == [1, 2]
assert trading_instructions["time_ns"].tolist() == [1, 2]
assert trading_instructions["action"].tolist() == ["TARGET", "CLOSE"]
assert trading_instructions["scaled_disequilibrium"].tolist() == [-1.25, -0.5]
assert trading_instructions["beta"].tolist() == [0.75, 0.75]
def test_calculate_pair_theo_executions_reads_sp_quant_instruction_columns():
trd_inst_df = pd.DataFrame(
{
"tstamp_ns": [1, 2],
"time_ns": [1, 2],
"tstamp": ["t1", "t2"],
"action": ["TARGET", "CLOSE"],
"quote_asset": ["USD", "USD"],
"assets": [
(
'{"AAA":{"reference_price":"100","strength":"0.5"},'
'"BBB":{"reference_price":"50","strength":"-0.5"}}'
),
'{"AAA":{"reference_price":"110"},"BBB":{"reference_price":"45"}}',
],
"scaled_disequilibrium": [-1.25, -0.5],
"beta": [0.75, 0.75],
}
)
executions = calculate_pair_theo_executions("AAA:USD-BBB:USD", trd_inst_df)
assert executions[
["time", "asset", "action", "scaled_disequilibrium", "beta"]
].to_dict("records") == [
{
"time": "t1",
"asset": "AAA",
"action": "TARGET",
"scaled_disequilibrium": -1.25,
"beta": 0.75,
},
{
"time": "t1",
"asset": "BBB",
"action": "TARGET",
"scaled_disequilibrium": -1.25,
"beta": 0.75,
},
{
"time": "t2",
"asset": "AAA",
"action": "CLOSE",
"scaled_disequilibrium": -0.5,
"beta": 0.75,
},
{
"time": "t2",
"asset": "BBB",
"action": "CLOSE",
"scaled_disequilibrium": -0.5,
"beta": 0.75,
},
]
def test_find_repo_root_and_normalize_directory():
repo_root = find_repo_root(Path("notebooks").resolve())
@@ -1030,6 +1167,8 @@ def test_create_panel_grids_use_analyze_button_and_hidden_pair_column():
"action",
"side",
"strength",
"scaled_disequilibrium",
"beta",
"size",
"price",
"usd_value",
+34 -29
View File
@@ -33,24 +33,26 @@ def create_panel_fixture_db(db_path: Path) -> None:
conn.execute(
"""
CREATE TABLE trading_instructions (
time_ns INTEGER,
tstamp TEXT,
tstamp_ns INTEGER,
type TEXT,
book_id TEXT,
strategy_id TEXT,
type TEXT,
data TEXT
action TEXT,
quote_asset TEXT,
assets TEXT,
scaled_disequilibrium REAL,
beta REAL
)
"""
)
conn.execute(
"""
CREATE TABLE ohlcv_1min (
CREATE TABLE market (
tstamp TEXT,
tstamp_ns INTEGER,
exch_acct TEXT,
exchange_id TEXT,
instrument_id TEXT,
interval_sec INTEGER,
open REAL,
high REAL,
low REAL,
@@ -73,44 +75,44 @@ def create_panel_fixture_db(db_path: Path) -> None:
),
)
conn.executemany(
"INSERT INTO trading_instructions VALUES (?, ?, ?, ?, ?, ?)",
"INSERT INTO trading_instructions VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
[
(
trading_day_start_ns,
"2026-06-17T00:00:00Z",
trading_day_start_ns,
"TARGET_POSITION",
"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"}}}'
),
"TARGET",
"USD",
'{"AAA":{"reference_price":"100","strength":"0.5"},'
'"BBB":{"reference_price":"50","strength":"-0.5"}}',
-1.25,
0.75,
),
(
trading_day_start_ns + 60_000_000_000,
"2026-06-17T00:01:00Z",
trading_day_start_ns + 60_000_000_000,
"CLOSE_POSITION",
"book",
"strategy-AAA:USD-BBB:USD",
"CLOSE_POSITION",
(
'{"action":"CLOSE","quote_asset":"USD","assets":'
'{"AAA":{"reference_price":"110"},'
'"BBB":{"reference_price":"45"}}}'
),
"CLOSE",
"USD",
'{"AAA":{"reference_price":"110"},'
'"BBB":{"reference_price":"45"}}',
-0.5,
0.75,
),
],
)
conn.executemany(
"INSERT INTO ohlcv_1min VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
"INSERT INTO market VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
[
(
"2026-06-17T00:00:00Z",
trading_day_start_ns,
"EXCH",
"EXCH",
"PAIR-AAA-USD",
60,
100.0,
100.0,
100.0,
@@ -123,9 +125,7 @@ def create_panel_fixture_db(db_path: Path) -> None:
"2026-06-17T00:00:00Z",
trading_day_start_ns,
"EXCH",
"EXCH",
"PAIR-BBB-USD",
60,
50.0,
50.0,
50.0,
@@ -169,7 +169,8 @@ def test_panel_app_uses_fast_list_template(tmp_path):
assert not hasattr(app, "refresh_button")
assert isinstance(view, module.pn.template.FastListTemplate)
assert view.title == module.APP_TITLE
assert view.sidebar_width == 430
assert view.theme is module.pn.template.DarkTheme
assert view.sidebar_width == module.APP_SIDEBAR_WIDTH
assert view.accent_base_color == module.APP_ACCENT_COLOR
assert view.header_background == module.APP_HEADER_COLOR
assert len(view.sidebar) == 1
@@ -191,8 +192,12 @@ def test_panel_app_calculates_pairs_and_selected_pair_outputs(tmp_path):
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.directory_input.sizing_mode == "stretch_width"
assert app.directory_input.width is None
assert app.file_select.sizing_mode == "stretch_width"
assert app.file_select.width is None
assert app.min_pctg_change_input.sizing_mode == "stretch_width"
assert app.min_pctg_change_input.width is None
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"