Aller au contenu

Dashboards

Strategy dashboards are Streamlit pages loaded by the hosted platform's dashboard image and by almanak dashboard locally. Both call your render_custom_dashboard() with the same arguments.

Anatomy of a dashboard

If a built-in template renderer fits your strategy, call it. The renderer owns the title, the strategy header (Deployment ID / pool / chain markdown), and the three audit sections (PnL, cost stack, trade tape). Do not wrap it with your own st.title(...) or audit-section helpers — that double-renders the title and the audit panels.

from almanak.framework.dashboard.templates import get_bollinger_config, render_ta_dashboard

def render_custom_dashboard(deployment_id, strategy_config, api_client, session_state):
    config = get_bollinger_config(period=20, std_dev=1.0)
    render_ta_dashboard(deployment_id, strategy_config, session_state, config)

Need to add summary cards or extra metrics? Call the renderer first and append your own widgets after — see strategies/accounting/lp/dashboard/ui.py and strategies/accounting/looping/dashboard/ui.py for committed reference implementations of that pattern (renderer + st.divider() + bespoke st.metric(...) cards below).

Need a custom title or to replace the audit sections entirely? Hand-roll the dashboard instead — see the next snippet. What you must NOT do is wrap render_*_dashboard() with extra st.title(...) / render_pnl_section(...) calls; the template already emits those, so you'll double-render.

If no template fits, hand-roll Streamlit and wire the audit primitives yourself (this is what almanak strat new scaffolds for blank / multi-step templates; LP / lending / TA / perp templates scaffold the template-renderer path above):

import streamlit as st
from almanak.framework.dashboard import (
    render_pnl_section, render_cost_stack_section, render_trade_tape_section,
)

def render_custom_dashboard(deployment_id, strategy_config, api_client, session_state):
    st.title("My Custom Strategy")
    render_pnl_section(deployment_id)
    # your indicator / position / performance UI
    render_cost_stack_section(deployment_id)
    render_trade_tape_section(deployment_id)

Audit primitives

almanak.framework.dashboard

Almanak Strategy Framework v2.0 - Dashboard

Public exports for dashboard data access, rendering, and PM integration. External consumers (PM dashboard, custom UIs) should import from here.

The streamlit-using render_*_section helpers are resolved lazily via :pep:562 __getattr__ so that gateway-side consumers — which import almanak.framework.dashboard.quant_aggregations to build PnL / cost-stack RPC responses — do not transitively pay the cost of loading streamlit at package init. The gateway image strips streamlit (see deploy/docker/strip-list-gateway.txt); an eager re-export here would ModuleNotFoundError on every dashboard RPC in production (VIB-4048). Regression guard: tests/gateway/test_imports_lean.py.

For strategy authors writing a dashboard/ui.py for their strategy, the recommended convention is to frame render_custom_dashboard() with three section helpers (VIB-3969) so accounting is visually QA'able locally and on the hosted platform from the same single-source code path:

  • render_pnl_section(deployment_id) — top, the 5-second eyeball
  • render_cost_stack_section(deployment_id) — bottom, life-to-date costs
  • render_trade_tape_section(deployment_id) — bottom, TX-level audit

Usage::

from almanak.framework.dashboard import (
    DashboardDataClient,
    Strategy,
    render_cost_stack_section,
    render_pnl_section,
    render_strategy_detail,
    render_strategy_timeline,
    render_trade_tape_section,
    strategy_from_pm_dict,
)

render_pnl_section

render_pnl_section(deployment_id: str) -> None

Render the 5-second-eyeball PnL section (VIB-3969).

Money Trail row: Deployed / NAV / Lifetime PnL / Net APR. The standard top-of-dashboard card so an operator answers "am I making or losing money?" before scrolling. Backed by the gateway's GetPnLSummary RPC; on RPC failure the section degrades to an info banner rather than crashing the page.

Conventionally placed immediately below the strategy title.

参数:

名称 类型 描述 默认
deployment_id str

The deployment id (passed straight through from render_custom_dashboard's first positional argument).

必需

render_cost_stack_section

render_cost_stack_section(
    deployment_id: str, *, heading: str = "### Cost Stack"
) -> None

Render the life-to-date Cost Stack section (VIB-3969).

Gas / Fees / Slippage / Earn — generic across primitives (every primitive emits these into transaction_ledger + accounting_events). Backed by the gateway's GetCostStack RPC; on RPC failure the section degrades to an info banner.

Conventionally placed at the start of an "Audit" section, just above the trade tape.

参数:

名称 类型 描述 默认
deployment_id str

The deployment id.

必需
heading str

Override the section heading. Pass an empty string to suppress the heading entirely (useful when composing inside a larger Audit panel that already has its own heading).

'### Cost Stack'

render_trade_tape_section

render_trade_tape_section(
    deployment_id: str, *, limit: int = 50
) -> None

Render the standard trade-tape section.

Conventionally placed at the bottom of every render_custom_dashboard() so accounting can be visually QA'd locally and on the hosted platform from the same code path. The underlying render_trade_tape reads through the gateway's DashboardService.GetTradeTape, which abstracts SQLite (local) and Postgres (hosted) — the section travels everywhere the gateway does.

参数:

名称 类型 描述 默认
deployment_id str

The deployment id (passed straight through from render_custom_dashboard's first positional argument).

必需
limit int

Most recent intents to fetch. Defaults to 50.

50

Template renderers

Pre-built sections for common strategy types. Each renderer is paired with factory configs that adapt the rendering to a specific protocol or indicator. Use these to fill the middle of the dashboard instead of hand-rolling indicator/position/performance UI.

Technical analysis (RSI, MACD, Bollinger, …)

almanak.framework.dashboard.templates.ta_dashboard

Technical Analysis (TA) Dashboard Template.

Reusable template for creating dashboards for indicator-based strategies. Supports any TA indicator with configurable signal logic and visualization.

Scope (single-position): the template drives one position on one base_token/quote_token pair. The 3 accounting sections (PnL, Cost Stack, Trade Tape) are baked in so every TA dashboard ships with full accounting by default.

  • Single indicator — pass one TADashboardConfig.
  • Multiple indicators (multi-signal, VIB-4897) — compose with :func:multi_ta_config. The template stacks one panel per indicator under a shared price chart (all on one time axis). Useful for confluence strategies (e.g. RSI + MACD + Bollinger).

For genuinely multi-position layouts the template is still the wrong tool — hand-roll from the section helpers (render_pnl_section, render_cost_stack_section, render_trade_tape_section) plus the primitive plot helpers in almanak.framework.dashboard.plots. See the dashboard blueprints.

Usage (single indicator): from almanak.framework.dashboard.templates import TADashboardConfig, render_ta_dashboard

config = TADashboardConfig(
    indicator_name="RSI", indicator_period=14,
    upper_threshold=70, lower_threshold=30, signal_type="reversion",
)

def render_custom_dashboard(deployment_id, strategy_config, api_client, session_state):
    # Pass deployment_id so the price chart follows the operator-selected
    # NAV range (24h/7d/30d) when one is picked (VIB-5114); omitting it
    # keeps the legacy recent-window fetch.
    session_state = prepare_ta_session_state(
        api_client, session_state, config, deployment_id=deployment_id
    )
    render_ta_dashboard(deployment_id, strategy_config, session_state, config)

Usage (multi-signal): from almanak.framework.dashboard.templates import ( get_rsi_config, get_macd_config, get_bollinger_config, multi_ta_config, prepare_ta_session_state, render_ta_dashboard, )

config = multi_ta_config(get_rsi_config(), get_macd_config(), get_bollinger_config())

def render_custom_dashboard(deployment_id, strategy_config, api_client, session_state):
    session_state = prepare_ta_session_state(
        api_client, session_state, config, deployment_id=deployment_id
    )
    render_ta_dashboard(deployment_id, strategy_config, session_state, config)

TADashboardConfig dataclass

TADashboardConfig(
    indicator_name: str,
    indicator_period: int = 14,
    secondary_periods: list[int] = list(),
    upper_threshold: float | None = None,
    lower_threshold: float | None = None,
    signal_type: Literal[
        "reversion", "momentum"
    ] = "reversion",
    value_format: str = "{:.1f}",
    value_suffix: str = "",
    custom_signal_fn: Callable[[dict[str, Any]], str]
    | None = None,
    chain: str = "Arbitrum",
    protocol: str = "Uniswap V3",
    base_token: str = "WETH",
    quote_token: str = "USDC",
    timeframe: str = "1h",
    extra_indicators: list[TADashboardConfig] = list(),
    display_window_seconds: int = DEFAULT_DISPLAY_WINDOW_SECONDS,
)

Configuration for a TA dashboard.

属性:

名称 类型 描述
indicator_name str

Name of the indicator (e.g., "RSI", "MACD", "CCI")

indicator_period int

Primary period for the indicator

secondary_periods list[int]

Additional periods (e.g., signal line for MACD)

upper_threshold float | None

Upper threshold for signals (overbought/bullish)

lower_threshold float | None

Lower threshold for signals (oversold/bearish)

signal_type Literal['reversion', 'momentum']

Type of signal logic - "reversion" or "momentum"

value_format str

Format string for displaying indicator value (e.g., "{:.1f}", "{:+.2f}")

value_suffix str

Suffix for indicator value (e.g., "%", " bps")

custom_signal_fn Callable[[dict[str, Any]], str] | None

Optional custom function for signal determination

chain str

Default chain name

protocol str

Default protocol name

base_token str

Default base token

quote_token str

Default quote token

timeframe str

OHLCV candle interval the dashboard fetches and computes the indicator series from — one of 1m/5m/15m/1h/4h/1d. Defaults to "1h" for back-compat. Must match the strategy's own data_granularity: otherwise the dashboard RSI/MACD/etc. line is a different series from the one the strategy decides on, so buy/sell markers won't align with the indicator band (VIB-4969). For the multi-signal layout the primary config's timeframe is authoritative (one shared OHLCV fetch); extras' timeframes are ignored, mirroring how their pair/chain are ignored.

extra_indicators list[TADashboardConfig]

Additional indicator configs to render as stacked panels (multi-signal layout, VIB-4897). Empty by default — the single-indicator path is unchanged. Compose via :func:multi_ta_config. Each extra contributes one more panel beneath the price chart; the extras' pair/chain/timeframe are ignored (the primary config drives the shared OHLCV fetch).

display_window_seconds int

Default visible span of the price/indicator x-axis, in seconds (VIB-5345). Decoupled from the FETCH span: the dashboard still fetches the wide candle window (timeframe cap + signal backfill) and computes the indicator over that full series — this only bounds how much is plotted by default so a freshly deployed strategy's recent action is not crowded into a multi-day axis. Anchored to the strategy's own timeline (see :func:~almanak.framework.dashboard.templates._ohlcv_window.display_window_bounds): the window never extends before the strategy start, and a hard floor of now - display_window_seconds guards against an unreliable reported start (VIB-5343). Defaults to one day (:data:~almanak.framework.dashboard.templates._ohlcv_window.DEFAULT_DISPLAY_WINDOW_SECONDS); set <= 0 to disable the cap and plot the full fetched span.

multi_ta_config

multi_ta_config(
    primary: TADashboardConfig, *extras: TADashboardConfig
) -> TADashboardConfig

Compose a multi-indicator (multi-signal) TA dashboard config.

The first config is the primary — it drives the dashboard title, the configured pair/chain, the shared OHLCV fetch, and the signal-status section. Each additional config renders as one more stacked indicator panel beneath the price chart. Indicator params (periods / thresholds) on the extras are honoured; their base_token / quote_token / chain are not — the primary's pair is authoritative so every panel shares one time axis.

Example::

config = multi_ta_config(
    get_rsi_config(period=14),
    get_macd_config(),
    get_bollinger_config(period=20, std_dev=2.0),
)
session_state = prepare_ta_session_state(api_client, session_state, config)
render_ta_dashboard(deployment_id, strategy_config, session_state, config)

Returns a new config (does not mutate primary).

prepare_ta_session_state

prepare_ta_session_state(
    api_client: Any,
    session_state: dict[str, Any] | None = None,
    config: TADashboardConfig | None = None,
    *,
    deployment_id: str | None = None,
) -> dict[str, Any]

Enrich session state for render_ta_dashboard (chart subplot).

Mirrors :func:prepare_lp_session_state: fetches OHLCV via the api_client, computes the indicator series client-side, reads the trade tape for buy/sell markers, and loads wallet balances for the Current Position section — strategy authors don't write any of that plumbing. Without this helper the chart section silently degrades to Price history data not available (nothing populates price_history / rsi_history / buy_signals / sell_signals) and the Current Position section reads 0.0000 / $0.00 / $0.00 (nothing populates base_balance / quote_balance / base_price).

参数:

名称 类型 描述 默认
api_client Any

DashboardAPIClient (or a duck-typed mock).

必需
session_state dict[str, Any] | None

Optional pre-existing state. Caller-supplied keys are preserved — never overwritten — so custom dashboards that already populate price_history keep working.

None
config TADashboardConfig | None

TADashboardConfig describing the indicator, pair, and chain. Required to know which token to fetch OHLCV for.

None
deployment_id str | None

Optional deployment id used to read the operator's selected NAV range from session_state (VIB-5114). When supplied AND the operator has picked a bounded range (24h/7d/30d) on the shared NAV chart, the candle granularity + the marker window follow that range. When None (the default, every legacy call site) or no range is selected, the fetch is byte-for-byte the configured recent window — full backward compatibility.

None

返回:

类型 描述
dict[str, Any]

The enriched session_state dict. Always returns; degrades to the

dict[str, Any]

unenriched state on any API failure rather than raising.

render_ta_dashboard

render_ta_dashboard(
    deployment_id: str,
    strategy_config: dict[str, Any],
    session_state: dict[str, Any],
    config: TADashboardConfig,
) -> None

Render a technical analysis dashboard using the provided configuration.

Single-position template. Renders one indicator panel by default; pass a :func:multi_ta_config (config.extra_indicators set) to stack one panel per indicator under a shared price chart (multi-signal, VIB-4897). Bakes in the 3 accounting sections (PnL → chart content → Cost Stack → Trade Tape). For multi-position layouts, compose a custom dashboard from the section helpers directly rather than parameterizing this template.

参数:

名称 类型 描述 默认
deployment_id str

The deployment identifier

必需
strategy_config dict[str, Any]

Strategy configuration dictionary

必需
session_state dict[str, Any]

Current session state with indicator values

必需
config TADashboardConfig

TADashboardConfig for this dashboard

必需

get_rsi_config

get_rsi_config(
    period: int = 14,
    overbought: float = 70,
    oversold: float = 30,
    timeframe: str = "1h",
) -> TADashboardConfig

Get pre-configured RSI dashboard config.

timeframe must match the strategy's data_granularity so the dashboard RSI is computed from the same candles the strategy decides on (VIB-4969). Defaults to "1h" for back-compat.

get_macd_config

get_macd_config(
    fast: int = 12,
    slow: int = 26,
    signal: int = 9,
    timeframe: str = "1h",
) -> TADashboardConfig

Get pre-configured MACD dashboard config.

timeframe must match the strategy's data_granularity (VIB-4969).

get_cci_config

get_cci_config(
    period: int = 20,
    overbought: float = 100,
    oversold: float = -100,
    timeframe: str = "1h",
) -> TADashboardConfig

Get pre-configured CCI dashboard config.

timeframe must match the strategy's data_granularity (VIB-4969).

get_stochastic_config

get_stochastic_config(
    fast_k: int = 14,
    slow_k: int = 3,
    slow_d: int = 3,
    overbought: float = 80,
    oversold: float = 20,
    timeframe: str = "1h",
) -> TADashboardConfig

Get pre-configured Stochastic dashboard config.

timeframe must match the strategy's data_granularity (VIB-4969).

get_atr_config

get_atr_config(
    period: int = 14, timeframe: str = "1h"
) -> TADashboardConfig

Get pre-configured ATR dashboard config.

timeframe must match the strategy's data_granularity (VIB-4969).

get_adx_config

get_adx_config(
    period: int = 14,
    trend_threshold: float = 25,
    timeframe: str = "1h",
) -> TADashboardConfig

Get pre-configured ADX dashboard config.

timeframe must match the strategy's data_granularity (VIB-4969).

get_bollinger_config

get_bollinger_config(
    period: int = 20,
    std_dev: float = 2.0,
    timeframe: str = "1h",
) -> TADashboardConfig

Get pre-configured Bollinger Bands dashboard config.

timeframe must match the strategy's data_granularity (VIB-4969).

Liquidity provision

almanak.framework.dashboard.templates.lp_dashboard

Liquidity Provider (LP) Dashboard Template.

Reusable template for creating dashboards for LP strategies on concentrated liquidity protocols like Uniswap V3, PancakeSwap V3, TraderJoe V2, and Aerodrome.

Scope (single-signal / single-position): the template renders one active LP position on one token0/token1 pair. LPSessionState is intentionally scalar (position_id, range_lower, range_upper); strategies that hold multiple LP NFTs simultaneously are not modelled here even though the gateway data model (PositionSummary.lp_positions) is multi-aware. The 3 accounting sections (PnL, Cost Stack, Trade Tape) are baked in so every LP dashboard ships with full accounting. For multi- position or multi-signal layouts, compose a custom dashboard from the section helpers (render_pnl_section, render_cost_stack_section, render_trade_tape_section) plus primitive plot helpers from almanak.framework.dashboard.plots directly. See the dashboard blueprints for the recommended composition.

Usage

from almanak.framework.dashboard.templates import ( LPDashboardConfig, render_lp_dashboard, prepare_lp_session_state, get_uniswap_v3_config, )

config = get_uniswap_v3_config(token0="WETH", token1="USDC")

def render_custom_dashboard(deployment_id, strategy_config, api_client, session_state): # Pass session_state + deployment_id so the pool price chart follows the # operator-selected NAV range (24h/7d/30d) when one is picked (VIB-5114); # omitting them keeps the legacy recent-window fetch. session_state = prepare_lp_session_state( api_client, session_state, config=config, deployment_id=deployment_id ) # Pass api_client so the template renders the gateway-backed # Positions registry + Position Lifecycle sections (PR #2373). render_lp_dashboard(deployment_id, strategy_config, session_state, config, api_client=api_client)

LP_CRITICAL_KEYS module-attribute

LP_CRITICAL_KEYS: list[str] = [
    "position_id",
    "range_lower",
    "range_upper",
    "total_value_usd",
    "is_active",
    "current_price",
    "in_range",
    "token0_amount",
    "token1_amount",
]

Keys that prepare_lp_session_state must produce and the template reads.

LP_LIVE_STATE_KEYS module-attribute

LP_LIVE_STATE_KEYS: frozenset[str] = frozenset(
    LP_CRITICAL_KEYS
) | {
    "current_position_id",
    "lower_tick",
    "upper_tick",
    "current_tick",
}

LP-critical state owned by the live gateway/market reads.

These keys reflect on-chain / market truth at render time. A caller-supplied session_state must not seed them ahead of the live reads — otherwise a stale, preserved dashboard state masks fresh state after the strategy has rebalanced on-chain (VIB-5025). The live read always wins; a caller value is used only as a last-resort fallback when the live path produced nothing (Empty != Zero), or when a caller explicitly pins the key via preserve_keys.

Any other key a caller passes (custom chart data such as position_history / price_history, fixture/display extras) is not live-owned and passes through untouched.

LPDashboardConfig dataclass

LPDashboardConfig(
    protocol: str = "uniswap_v3",
    token0: str = "WETH",
    token1: str = "USDC",
    fee_tier: str = "0.30%",
    chain: str = DEFAULT_CHAIN,
    show_liquidity_distribution: bool = True,
    show_position_history: bool = True,
    show_impermanent_loss: bool = True,
    show_fee_accumulation: bool = True,
    invert_prices: bool = False,
    position_bounds_ratio: float | None = 0.8,
    pool_address: str | None = None,
    token0_address: str | None = None,
    token1_address: str | None = None,
    timeframe: str = "1h",
)

Configuration for an LP dashboard.

属性:

名称 类型 描述
protocol str

Protocol name (e.g., "uniswap_v3", "aerodrome", "traderjoe_v2")

token0 str

First token symbol

token1 str

Second token symbol

fee_tier str

Fee tier display string (e.g., "0.30%")

chain str

Chain name

show_liquidity_distribution bool

Whether to show liquidity distribution chart

show_position_history bool

Whether to show position history chart

show_impermanent_loss bool

Whether to show IL tracking

show_fee_accumulation bool

Whether to show fee accumulation chart

invert_prices bool

Whether to invert price display

position_bounds_ratio float | None

Ratio for position bounds lines (None to disable)

timeframe str

OHLCV candle interval for the price-history chart — one of 1m/5m/15m/1h/4h/1d. Defaults to "1h" for back-compat. Set it to the strategy's data_granularity so the price chart matches the cadence the strategy actually trades on (VIB-4969); the recent-window candle count scales per timeframe.

LPSessionState

Bases: TypedDict

Keys expected by render_lp_dashboard() in session_state.

Use prepare_lp_session_state(api_client, config=config) to populate this automatically from the gateway.

Keys from strategy state (read directly, no mapping): position_id: Active LP position identifier. range_lower: Lower price bound of the LP position. range_upper: Upper price bound of the LP position. total_value_usd: Total position value in USD.

Keys derived/loaded by prepare_lp_session_state(): is_active: Whether a position is currently active. current_price: Current market price of token0 in USD. in_range: Whether current_price is within [range_lower, range_upper]. token0_amount: Amount of token0 in the position. token1_amount: Amount of token1 in the position.

Optional keys (strategy may or may not provide): total_fees_usd, impermanent_loss_pct, net_pnl_usd: Performance metrics. tick_data, lower_tick, upper_tick, current_tick: Liquidity distribution. position_history, price_history, fee_history, il_history: Chart data.

prepare_lp_session_state

prepare_lp_session_state(
    api_client: Any,
    session_state: dict[str, Any] | None = None,
    config: LPDashboardConfig | None = None,
    preserve_keys: Collection[str] | None = None,
    *,
    deployment_id: str | None = None,
) -> dict[str, Any]

Load strategy data from the gateway and enrich for the LP dashboard.

The dashboard is a live view: the gateway/market reads are the source of truth (blueprint 22/23; VIB-2838 "dashboard as a validation client"). The result is therefore built from the live api_client.get_state() read first, then enriched with derived fields (is_active, in_range) and live market data (current_price, token amounts).

A caller-supplied session_state contributes custom / non-live keys only (custom chart data such as position_history / price_history, fixture/display extras). The LP-critical live-state keys (:data:LP_LIVE_STATE_KEYS) are owned by the live reads and are never seeded from the caller ahead of them — this prevents a stale, preserved dashboard state from masking fresh on-chain state after a rebalance (VIB-5025). A caller value for a live key is used only as a last-resort fallback when the live path produced nothing (Empty != Zero), or when the caller explicitly pins the key via preserve_keys.

参数:

名称 类型 描述 默认
api_client Any

DashboardAPIClient instance.

必需
session_state dict[str, Any] | None

Optional pre-existing state. Non-live keys pass through and are preserved; live-state keys are refreshed from the gateway. Pass None (or an empty dict) for a pure fresh fetch.

None
config LPDashboardConfig | None

LPDashboardConfig -- needed to know which token to price. If None, current_price will not be fetched.

None
preserve_keys Collection[str] | None

Optional explicit opt-out. Keys listed here keep the caller-provided value over the live read (e.g. a replay / snapshot dashboard that intentionally renders a historical state rather than live state). The safe default (None) refreshes every live key.

None
deployment_id str | None

Optional deployment id used to read the operator's selected NAV range from session_state (VIB-5114). When supplied AND a bounded range (24h/7d/30d) is selected on the shared NAV chart, the pool price-history candles follow that range's granularity. When None (the default, every legacy call site) or no range is selected, the OHLCV fetch is byte-for-byte the configured recent window. (The LP price chart has no trade-tape markers, so only the candle granularity follows the range.)

None

返回:

类型 描述
dict[str, Any]

Enriched dict containing all :data:LP_CRITICAL_KEYS.

render_lp_dashboard

render_lp_dashboard(
    deployment_id: str,
    strategy_config: dict[str, Any],
    session_state: dict[str, Any],
    config: LPDashboardConfig,
    api_client: Any | None = None,
) -> None

Render an LP strategy dashboard using the provided configuration.

Single-signal / single-position template — renders one active LP position on one configured pair. Bakes in the 3 accounting sections (PnL → primitive content → Cost Stack → Trade Tape). For multi- position or multi-signal layouts, compose a custom dashboard from the section helpers directly rather than parameterizing this template.

参数:

名称 类型 描述 默认
deployment_id str

The deployment identifier

必需
strategy_config dict[str, Any]

Strategy configuration dictionary

必需
session_state dict[str, Any]

Current session state with position data. Use :func:prepare_lp_session_state to populate this from the gateway before calling this function.

必需
config LPDashboardConfig

LPDashboardConfig for this dashboard

必需
api_client Any | None

Optional DashboardAPIClient (the same one passed into render_custom_dashboard). When supplied, the template renders the gateway-backed Positions registry and Position Lifecycle sections so AlmanakCode-generated LP dashboards inherit the same tables the local detail page shows (PR 2 / Problem A2). When None (legacy callers), those sections are skipped silently — backward-compatible with every existing render_lp_dashboard(...) call site.

None

registry_handles_from_trade_tape

registry_handles_from_trade_tape(
    api_client: Any, *, limit: int = 200
) -> dict[str, str]

Map position_id (e.g. UniV3 NFT tokenId) → the strategy's actual registry handle.

Source: the trade-tape join (ledger × accounting × position event). Every accounting OPEN/CLOSE row carries position_reference.registry_handle — the handle the strategy itself stamped on the intent — alongside the joined position_id. This is the SAME provenance the Trade Tape headline chip and the registry table surface, so the Position Status cards and the Liquidity Distribution legend can never disagree with them (VIB-5073: the lp_dual dashboard used to label the Nth distinct position_id leg_<N>, so a rebalanced leg — same handle, new tokenId — rendered as a phantom leg_3 that exists nowhere in the strategy config).

Never synthesizes a handle: positions whose events carry no registry_handle are simply absent from the map. Callers must fall back to a clearly-non-handle label (the tokenId / a generic placeholder).

Rows arrive newest-first (gateway sorts timestamp DESC) and the first handle seen per position_id wins, so a re-bound handle reflects the most recent accounting write.

Returns {} on any failure — never raises (dashboard render path).

get_uniswap_v3_config

get_uniswap_v3_config(
    token0: str = "WETH",
    token1: str = "USDC",
    fee_tier: str = "0.30%",
    chain: str = "arbitrum",
    timeframe: str = "1h",
) -> LPDashboardConfig

Get pre-configured Uniswap V3 LP dashboard config.

timeframe sets the price-chart candle interval (VIB-4969); defaults to "1h".

get_aerodrome_config

get_aerodrome_config(
    token0: str = "WETH",
    token1: str = "USDC",
    pool_type: str = "volatile",
    chain: str = "base",
    timeframe: str = "1h",
) -> LPDashboardConfig

Get pre-configured Aerodrome LP dashboard config.

timeframe sets the price-chart candle interval (VIB-4969); defaults to "1h".

get_traderjoe_v2_config

get_traderjoe_v2_config(
    token0: str = "WAVAX",
    token1: str = "USDC",
    bin_step: str = "20",
    chain: str = "avalanche",
    timeframe: str = "1h",
) -> LPDashboardConfig

Get pre-configured TraderJoe V2 LP dashboard config.

timeframe sets the price-chart candle interval (VIB-4969); defaults to "1h".

get_pancakeswap_v3_config

get_pancakeswap_v3_config(
    token0: str = "WBNB",
    token1: str = "USDT",
    fee_tier: str = "0.25%",
    chain: str = "bsc",
    timeframe: str = "1h",
) -> LPDashboardConfig

Get pre-configured PancakeSwap V3 LP dashboard config.

timeframe sets the price-chart candle interval (VIB-4969); defaults to "1h".

Lending

almanak.framework.dashboard.templates.lending_dashboard

Lending Protocol Dashboard Template.

Reusable template for creating dashboards for lending strategies on protocols like Aave V3, Morpho Blue, Compound V3, and Spark.

Scope (single-signal / single-position): the template renders one collateral / borrow pair with one scalar health factor and LTV — the shape of a single supply-borrow loop. Multi-collateral is partially supported through collateral_assets (a dict feeding the breakdown plot), but the headline metrics remain singular. The 3 accounting sections (PnL, Cost Stack, Trade Tape) are baked in so every lending dashboard ships with full accounting. For multi-signal layouts (e.g. "supply on Aave + supply on Morpho" as separate motivations), do not parameterize this template — write a custom dashboard composed from the section helpers (render_pnl_section, render_cost_stack_section, render_trade_tape_section) plus primitive plot helpers from almanak.framework.dashboard.plots directly. See the dashboard blueprints for the recommended composition.

Usage

from almanak.framework.dashboard.templates import LendingDashboardConfig, render_lending_dashboard

config = LendingDashboardConfig( protocol="aave_v3", collateral_token="WETH", borrow_token="USDC", )

def render_custom_dashboard(deployment_id, strategy_config, api_client, session_state): render_lending_dashboard(deployment_id, strategy_config, session_state, config)

LendingDashboardConfig dataclass

LendingDashboardConfig(
    protocol: str = "aave_v3",
    collateral_token: str = "WETH",
    borrow_token: str = "USDC",
    chain: str = DEFAULT_CHAIN,
    liquidation_threshold: float = 1.0,
    safe_threshold: float = 1.5,
    max_ltv: float = 0.8,
    liquidation_ltv: float = 0.85,
    show_health_factor: bool = True,
    show_ltv: bool = True,
    show_collateral_breakdown: bool = True,
    show_rate_comparison: bool = False,
)

Configuration for a lending dashboard.

属性:

名称 类型 描述
protocol str

Protocol name (e.g., "aave_v3", "morpho_blue", "compound_v3")

collateral_token str

Primary collateral token symbol

borrow_token str

Primary borrow token symbol

chain str

Chain name

liquidation_threshold float

Health factor threshold for liquidation (default 1.0)

safe_threshold float

Health factor threshold considered safe (default 1.5)

max_ltv float

Maximum LTV ratio (default 0.8)

liquidation_ltv float

LTV at which liquidation occurs (default 0.85)

show_health_factor bool

Whether to show health factor gauge

show_ltv bool

Whether to show LTV ratio visualization

show_collateral_breakdown bool

Whether to show collateral breakdown

show_rate_comparison bool

Whether to show rate comparison (for multi-protocol)

prepare_lending_session_state

prepare_lending_session_state(
    api_client: Any,
    *,
    session_state: dict[str, Any],
    config: LendingDashboardConfig,
    strategy_config: dict[str, Any] | None = None,
) -> dict[str, Any]

Hydrate generic lending dashboard fields from strategy state.

Hosted/custom dashboards receive raw strategy persistence, which often stores domain names such as supplied_token_amount and borrowed_token_amount. The lending template renders generic fields (collateral_amount, borrowed_amount, ltv, health_factor). This adapter keeps strategy dashboards thin while making the SDK template useful for Aave-style supply/borrow loops.

render_lending_dashboard

render_lending_dashboard(
    deployment_id: str,
    strategy_config: dict[str, Any],
    session_state: dict[str, Any],
    config: LendingDashboardConfig,
) -> None

Render a lending strategy dashboard using the provided configuration.

Single-signal / single-position template — one collateral/borrow pair with scalar health factor and LTV. Bakes in the 3 accounting sections (PnL → primitive content → Cost Stack → Trade Tape). For multi- position or multi-signal layouts, compose a custom dashboard from the section helpers directly rather than parameterizing this template.

参数:

名称 类型 描述 默认
deployment_id str

The deployment identifier

必需
strategy_config dict[str, Any]

Strategy configuration dictionary

必需
session_state dict[str, Any]

Current session state with position data

必需
config LendingDashboardConfig

LendingDashboardConfig for this dashboard

必需

get_aave_v3_config

get_aave_v3_config(
    collateral_token: str = "WETH",
    borrow_token: str = "USDC",
    chain: str = DEFAULT_CHAIN,
) -> LendingDashboardConfig

Get pre-configured Aave V3 lending dashboard config.

get_morpho_blue_config

get_morpho_blue_config(
    collateral_token: str = "wstETH",
    borrow_token: str = "USDC",
    chain: str = "ethereum",
) -> LendingDashboardConfig

Get pre-configured Morpho Blue lending dashboard config.

get_compound_v3_config

get_compound_v3_config(
    collateral_token: str = "WETH",
    borrow_token: str = "USDC",
    chain: str = "ethereum",
) -> LendingDashboardConfig

Get pre-configured Compound V3 lending dashboard config.

get_spark_config

get_spark_config(
    collateral_token: str = "WETH",
    borrow_token: str = "DAI",
    chain: str = "ethereum",
) -> LendingDashboardConfig

Get pre-configured Spark lending dashboard config.

Perpetuals

almanak.framework.dashboard.templates.perp_dashboard

Perpetual Futures Dashboard Template.

Reusable template for creating dashboards for perpetual trading strategies on protocols like GMX V2 and Hyperliquid.

Scope (single-signal / single-position): the template renders one perp position on one market. has_position is a boolean and entry_price / is_long / liquidation_price are scalars; an account holding multiple perps simultaneously is not modelled here. The 3 accounting sections (PnL, Cost Stack, Trade Tape) are baked in so every perp dashboard ships with full accounting. For multi-position or multi-signal layouts (e.g. a basket of perp legs hedging spot exposure), do not parameterize this template — write a custom dashboard composed from the section helpers (render_pnl_section, render_cost_stack_section, render_trade_tape_section) plus primitive plot helpers from almanak.framework.dashboard.plots directly. See the dashboard blueprints for the recommended composition.

Usage

from almanak.framework.dashboard.templates import PerpDashboardConfig, render_perp_dashboard

config = PerpDashboardConfig( protocol="gmx_v2", market="ETH/USD", collateral_token="WETH", )

def render_custom_dashboard(deployment_id, strategy_config, api_client, session_state): render_perp_dashboard(deployment_id, strategy_config, session_state, config)

PerpDashboardConfig dataclass

PerpDashboardConfig(
    protocol: str = "gmx_v2",
    market: str = "ETH/USD",
    collateral_token: str = "WETH",
    chain: str = DEFAULT_CHAIN,
    max_leverage: float = 50.0,
    safe_leverage: float = 10.0,
    show_position_dashboard: bool = True,
    show_funding_history: bool = True,
    show_leverage_gauge: bool = True,
    show_liquidation_levels: bool = True,
)

Configuration for a perpetual futures dashboard.

属性:

名称 类型 描述
protocol str

Protocol name (e.g., "gmx_v2", "hyperliquid")

market str

Market identifier (e.g., "ETH/USD", "BTC/USD")

collateral_token str

Collateral token symbol

chain str

Chain name

max_leverage float

Maximum allowed leverage

safe_leverage float

Recommended safe leverage

show_position_dashboard bool

Whether to show the main position dashboard

show_funding_history bool

Whether to show funding rate history

show_leverage_gauge bool

Whether to show leverage gauge

show_liquidation_levels bool

Whether to show liquidation levels

render_perp_dashboard

render_perp_dashboard(
    deployment_id: str,
    strategy_config: dict[str, Any],
    session_state: dict[str, Any],
    config: PerpDashboardConfig,
) -> None

Render a perpetual futures strategy dashboard using the provided configuration.

Single-signal / single-position template — one perp position on one market. Bakes in the 3 accounting sections (PnL → primitive content → Cost Stack → Trade Tape). For multi-position or multi-signal layouts, compose a custom dashboard from the section helpers directly rather than parameterizing this template.

参数:

名称 类型 描述 默认
deployment_id str

The deployment identifier

必需
strategy_config dict[str, Any]

Strategy configuration dictionary

必需
session_state dict[str, Any]

Current session state with position data

必需
config PerpDashboardConfig

PerpDashboardConfig for this dashboard

必需

get_gmx_v2_config

get_gmx_v2_config(
    market: str = "ETH/USD",
    collateral_token: str = "WETH",
    chain: str = DEFAULT_CHAIN,
) -> PerpDashboardConfig

Get pre-configured GMX V2 perpetuals dashboard config.

get_hyperliquid_config

get_hyperliquid_config(
    market: str = "ETH",
    collateral_token: str = "USDC",
    chain: str = "hyperliquid",
) -> PerpDashboardConfig

Get pre-configured Hyperliquid perpetuals dashboard config.

Prediction markets

almanak.framework.dashboard.templates.prediction_dashboard

Prediction Market Dashboard Template.

Reusable template for creating dashboards for prediction market strategies on platforms like Polymarket.

Scope (single-signal / single-position): the template renders one active market with one YES/NO position. market_id / yes_shares / no_shares / cost_basis are scalars; an account holding positions across multiple markets simultaneously is not modelled in the headline panels (the optional tracked_markets plot is informational only). The 3 accounting sections (PnL, Cost Stack, Trade Tape) are baked in so every prediction dashboard ships with full accounting. For multi-market or multi-signal layouts (e.g. an arbitrage basket spanning N markets), do not parameterize this template — write a custom dashboard composed from the section helpers (render_pnl_section, render_cost_stack_section, render_trade_tape_section) plus primitive plot helpers from almanak.framework.dashboard.plots directly. See the dashboard blueprints for the recommended composition.

Usage

from almanak.framework.dashboard.templates import PredictionDashboardConfig, render_prediction_dashboard

protocol defaults to the connector default ("polymarket"); pass

protocol="" to override for another prediction venue.

config = PredictionDashboardConfig()

def render_custom_dashboard(deployment_id, strategy_config, api_client, session_state): render_prediction_dashboard(deployment_id, strategy_config, session_state, config)

PredictionDashboardConfig dataclass

PredictionDashboardConfig(
    protocol: str = (
        lambda: _default_prediction_protocol()
        or "polymarket"
    )(),
    chain: str = "polygon",
    show_position_overview: bool = True,
    show_probability_chart: bool = True,
    show_market_outcomes: bool = True,
    show_arbitrage_analysis: bool = True,
    show_pnl_breakdown: bool = True,
)

Configuration for a prediction market dashboard.

属性:

名称 类型 描述
protocol str

Protocol name (e.g., "polymarket")

chain str

Chain name

show_position_overview bool

Whether to show position overview

show_probability_chart bool

Whether to show probability over time

show_market_outcomes bool

Whether to show market outcomes comparison

show_arbitrage_analysis bool

Whether to show arbitrage opportunity analysis

show_pnl_breakdown bool

Whether to show PnL breakdown

render_prediction_dashboard

render_prediction_dashboard(
    deployment_id: str,
    strategy_config: dict[str, Any],
    session_state: dict[str, Any],
    config: PredictionDashboardConfig,
) -> None

Render a prediction market strategy dashboard using the provided configuration.

Single-signal / single-position template — one active market with one YES/NO position. Bakes in the 3 accounting sections (PnL → primitive content → Cost Stack → Trade Tape). For multi-position or multi-signal layouts, compose a custom dashboard from the section helpers directly rather than parameterizing this template.

参数:

名称 类型 描述 默认
deployment_id str

The deployment identifier

必需
strategy_config dict[str, Any]

Strategy configuration dictionary

必需
session_state dict[str, Any]

Current session state with position data

必需
config PredictionDashboardConfig

PredictionDashboardConfig for this dashboard

必需

get_polymarket_config

get_polymarket_config() -> PredictionDashboardConfig

Get pre-configured Polymarket dashboard config.

get_polymarket_arbitrage_config

get_polymarket_arbitrage_config() -> (
    PredictionDashboardConfig
)

Get pre-configured Polymarket arbitrage dashboard config.