DOCUMENTATION

Podium is a launch-to-live operating layer for a lean systematic equity fund. Today you can build, backtest, and paper-trade deterministic strategies with the Strategy SDK. The wider operating layer — data readiness, signal governance, risk, construction, orders, reconciliation, and the evidence vault — is rolling out module by module.

PLATFORM MODULES

Every module mapped — what is live today vs. coming soon

STRATEGY SDK REFERENCE

Full SDK docs — quickstart, architecture, data, execution, API reference, examples

STRATEGY SDK

All strategies extend Strategy and implement universe() and signal() to return target portfolio weights.

REQUIRED & OPTIONAL METHODS

initialize(ctx) optional

Called once on the first tick. Use for setting parameters or loading state.

universe(ctx) -> list[str] required

Return the list of symbols to consider. Called before each signal() invocation.

signal(ctx) -> dict[str, float] required

Return target weights as a dict mapping symbol to weight (0.0-1.0). Weights are normalized to sum to 1.0 for long-only strategies.

risk_limits(ctx) -> RiskLimits optional

Override default risk limits per strategy. Returns a RiskLimits dataclass (defaults are used if not overridden). See Risk Limits docs for all available parameters.

STRATEGY CONTEXT

Every method receives a StrategyContext with:

python
# StrategyContext fields available in every method call:

ctx.date             # Current trading date (str, YYYY-MM-DD)
ctx.portfolio        # PortfolioState (positions, PnL, exposures, drawdown)
ctx.data             # DataAccessor for market data
ctx.config           # dict of strategy config
ctx.security_master  # pd.DataFrame of symbol metadata
ctx.ops              # Alpha operators namespace (ctx.ops.rank, ...)
ctx.run_skill_script(skill, script, input)  # call a bundled skill

DATA ACCESSOR

python
# DataAccessor methods (all return pandas objects):

ctx.data.ohlcv(symbols=None, lookback=126)   # raw OHLCV (MultiIndex)
ctx.data.returns(lookback=126)               # daily returns panel
ctx.data.close(lookback=126)                 # adjusted close panel
ctx.data.open(lookback=126)                  # open panel
ctx.data.high(lookback=126)                  # high panel
ctx.data.low(lookback=126)                   # low panel
ctx.data.volume(lookback=126)                # volume panel
ctx.data.vwap(lookback=126)                  # VWAP panel
ctx.data.fundamentals(symbol)                # fundamentals dataset
ctx.data.sector(symbol)                      # sector string
ctx.data.market_cap(symbol)                  # market cap float

RISK LIMITS OVERRIDE

python
# Optional: override default risk limits.
# Returns a RiskLimits dataclass (not a plain dict).
from podium_sdk import RiskLimits, StrategyContext

def risk_limits(self, ctx: StrategyContext) -> RiskLimits:
    return RiskLimits(
        max_position_pct=0.10,   # 10% max per position
        max_sector_pct=0.35,     # 35% max per sector
        max_drawdown_pct=0.20,   # 20% max drawdown
        min_positions=5,         # minimum 5 positions
    )

COMPLETE WORKING EXAMPLE — MOMENTUM RANKING

python
from podium_sdk import Strategy, StrategyContext

class MomentumRanking(Strategy):
    """6-month momentum, top 20 by trailing return, equal weight."""
    TOP_N = 20
    LOOKBACK_DAYS = 126

    def initialize(self, ctx: StrategyContext) -> None:
        # Called once on first tick. Use for
        # loading parameters or state.
        pass

    def universe(self, ctx: StrategyContext) -> list[str]:
        # Return the list of symbols to consider.
        # Called before each signal() call.
        returns = ctx.data.returns(lookback=self.LOOKBACK_DAYS + 5)
        if returns.empty:
            return []
        return list(returns.columns)

    def signal(self, ctx: StrategyContext) -> dict[str, float]:
        # Return target weights {symbol: weight}.
        # Weights are normalized to sum to 1.0.
        returns = ctx.data.returns(lookback=self.LOOKBACK_DAYS)
        if returns.empty:
            return {}
        cum_return = (1 + returns).prod() - 1
        ranked = cum_return.sort_values(ascending=False)
        top_n = ranked.head(self.TOP_N)
        if len(top_n) == 0:
            return {}
        weight = 1.0 / len(top_n)
        return {sym: round(weight, 6) for sym in top_n.index}

USER GUIDES

In-depth manuals for backtesting, strategy development, and deployment