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
First Backtest
Step-by-step tutorial: clone a template, run a backtest, and interpret results.
Risk Limits
Every guardrail check explained with numeric examples of what happens on breach.
Long-Short Strategies
Gross vs net exposure, borrow costs, long/short attribution, and archetypes.
STRATEGY SDK REFERENCE
Full SDK docs — quickstart, architecture, data, execution, API reference, examples
Alpha Operators
40 formulaic operators via ctx.ops — rank, decay, correlation, indicators.
Skill Bundles
Author SKILL.md + sandboxed scripts callable from signal().
Strategy Templates
8 long-only and long-short templates to clone and customize.
Deployment & Paper Trading
Deploy, daily ticks, monitoring, and T+1 reconciliation.
Data Sources
Databento OHLCV + FMP fundamentals: coverage and fields.
Security Model
Sandbox isolation, AST scanning, and env restrictions.
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:
# 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 skillDATA ACCESSOR
# 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 floatRISK LIMITS OVERRIDE
# 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
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