Release v1.0.2

This commit is contained in:
Oleg Sheynin
2026-07-29 00:39:10 +00:00
parent 49c91e5d85
commit a3e5acd765
8 changed files with 764 additions and 96 deletions
+85
View File
@@ -20,6 +20,22 @@ OHLCV_1MIN_COLUMNS = ("tstamp", "tstamp_ns", "exch_acct", "instrument_id", "clos
INITIAL_THEO_CAPITAL_USD = 10_000.0
SQLITE_EXTENSIONS = {".db", ".sqlite", ".sqlite3"}
PAIR_NAME_DISPLAY_SUFFIX = ":USD"
PAIR_NAME_VALUE_COLUMN = "_pair_name_value"
ANALYZE_BUTTON_COLUMN = "analyze"
ANALYZE_BUTTON_HTML = (
'<button type="button" title="Analyze pair" aria-label="Analyze pair" '
'style="padding: 1px 6px; line-height: 1.2;">&#9654;</button>'
)
SELECTED_PAIR_EXECUTION_DISPLAY_COLUMNS = [
"time",
"asset",
"action",
"side",
"strength",
"size",
"price",
"usd_value",
]
INTERACTIVE_TABLE_CSS = """
table.dataTable,
table.dataTable th,
@@ -1081,6 +1097,75 @@ def format_pair_names_for_display(
return formatted
def format_pair_theo_ret_for_analyze_grid(pair_theo_ret: pd.DataFrame) -> pd.DataFrame:
"""Format pair TheoRet rows for an Analyze-button grid.
The visible pair name is display-cleaned, while the original pair name is
retained in a hidden column for callbacks that need the calculation key.
"""
if "pair_name" not in pair_theo_ret.columns:
raise ValueError("pair TheoRet dataframe missing column: pair_name")
formatted = format_pair_names_for_display(pair_theo_ret)
formatted[PAIR_NAME_VALUE_COLUMN] = pair_theo_ret["pair_name"].to_numpy()
return formatted
def pair_name_from_analyze_event(table: Any, event: Any) -> str:
"""Resolve the full pair name from a Panel Tabulator click event."""
if PAIR_NAME_VALUE_COLUMN not in table.value.columns:
raise ValueError(f"Analyze table missing column: {PAIR_NAME_VALUE_COLUMN}")
pair_name = table.value[PAIR_NAME_VALUE_COLUMN].iloc[event.row]
if pd.isna(pair_name) or not str(pair_name):
raise ValueError(f"Analyze row {event.row} does not contain a pair name")
return str(pair_name)
def create_pair_theo_ret_analyze_grid(
pair_theo_ret_display: pd.DataFrame,
*,
height: int = 420,
) -> Any:
"""Create a sortable Panel grid with a compact Analyze button column."""
import panel as pn
return pn.widgets.Tabulator(
pair_theo_ret_display,
buttons={ANALYZE_BUTTON_COLUMN: ANALYZE_BUTTON_HTML},
hidden_columns=[PAIR_NAME_VALUE_COLUMN],
show_index=False,
pagination=None,
layout="fit_data_table",
height=height,
sizing_mode="fixed",
selectable=False,
)
def create_selected_pair_executions_grid(
dataframe: pd.DataFrame | None = None,
*,
height: int = 320,
) -> Any:
"""Create a sortable Panel grid for selected-pair theoretical executions."""
import panel as pn
source = (
dataframe
if dataframe is not None
else pd.DataFrame(columns=SELECTED_PAIR_EXECUTION_DISPLAY_COLUMNS)
)
return pn.widgets.Tabulator(
source.reindex(columns=SELECTED_PAIR_EXECUTION_DISPLAY_COLUMNS),
show_index=False,
pagination=None,
layout="fit_data_table",
height=height,
sizing_mode="fixed",
selectable=False,
)
def add_total_pnl(pair_theo_ret: pd.DataFrame) -> pd.DataFrame:
"""Return a copy of pair TheoRet rows with total realized plus unrealized PnL."""
required_columns = {"realized_pnl", "unrealized_pnl"}