"Price is the effect. The order book is the cause."
In systematic trading, this principle drives every decision. But what happens when your trading system requires market data that no standard API delivers? What happens when your firm's proprietary indicators demand order book reconstruction logic that lives nowhere in documentation? What happens when the 50-millisecond latency your execution layer demands cannot survive the round-trip through a generic REST endpoint?
These are the problems that drove the design of the TickDB SKILL protocol. SKILL is not a plugin system. It is not a webhook handler. It is a first-class extension architecture that lets development teams embed custom market data logic directly into the TickDB execution environment — with full access to real-time depth data, configurable alerting thresholds, and a deployment model that supports both cloud-native integration and fully air-gapped private installations.
This article provides a complete technical walkthrough of the SKILL development lifecycle: from understanding the protocol specification and authoring your first custom function, to deploying a production-grade SKILL in a private infrastructure environment.
Understanding the TickDB SKILL Protocol
What SKILL Is — and What It Is Not
The SKILL protocol sits at the intersection of market data delivery and business logic execution. Unlike traditional API integrations where your system polls for data and applies logic downstream, SKILL allows you to deploy logic upstream — directly adjacent to the data source.
This architectural shift matters for three reasons.
Latency elimination at the source. When your order book imbalance calculation runs inside your application after receiving a depth snapshot, you have already incurred network transit latency, deserialization overhead, and processing delay. When that calculation runs inside a SKILL function that intercepts the depth stream before transmission, the output arrives at your system pre-computed.
Stateful context without client-side maintenance. Standard WebSocket feeds deliver point-in-time snapshots. A SKILL function can maintain rolling windows, track cumulative pressure ratios across events, and surface alerts only when thresholds are crossed — without requiring your client application to manage any of that state.
Enterprise isolation and compliance. For firms operating in regulated environments — asset managers, prop desks, family offices — the ability to deploy proprietary calculation logic inside a controlled infrastructure boundary is not optional. SKILL supports fully air-gapped private deployments where no market data leaves the firm's network.
The Protocol Architecture
The SKILL protocol operates as a lightweight middleware layer between TickDB's core data engines and the delivery endpoint (your trading system, dashboard, or alert handler). The protocol defines three core interaction patterns.
| Pattern | Description | Use case |
|---|---|---|
| Pre-process | Function receives raw tick/depth data before delivery | Apply custom filters, compute derived metrics |
| Trigger | Function monitors a data stream and fires on condition | Alert when spread exceeds threshold |
| Enrich | Function appends calculated fields to outgoing payload | Add moving average, volatility cone, pressure ratio |
Every SKILL function follows a standard interface contract. The contract specifies input schema, output schema, configuration parameters, and lifecycle hooks (initialize, execute, terminate). This contract is declared in a skill.yaml manifest that ships with every SKILL package.
The SKILL Development Specification
The skill.yaml Manifest
Every SKILL begins with a YAML manifest that declares the function's identity, interface, and resource requirements. The manifest serves two purposes: it is the contract that the TickDB runtime validates against, and it is the configuration surface that operators use to deploy and parameterize the function.
apiVersion: tickdb.io/v1
kind: Skill
metadata:
name: order-pressure-monitor
version: "1.2.0"
description: >
Computes real-time buy/sell pressure ratio from depth L1/L3 snapshots.
Emits alerts when ratio crosses user-defined thresholds within a rolling window.
spec:
runtime:
language: python3
entrypoint: pressure_monitor.run
memoryLimit: 256Mi
cpuLimit: "0.5"
inputs:
- channel: depth
symbols: ["*"] # or explicit list: ["NVDA.US", "TSLA.US"]
levels: [1, 3] # L1 = best bid/ask, L3 = extended depth
outputs:
- name: pressure_ratio
type: float
schema:
timestamp: int64
symbol: string
bid_pressure: float
ask_pressure: float
ratio: float
window_size: int
- name: alert
type: event
schema:
timestamp: int64
symbol: string
trigger_type: string # "threshold_cross" | "spread_widening"
ratio_before: float
ratio_after: float
config:
- name: window_seconds
type: int
default: 60
description: Rolling window duration in seconds
- name: alert_threshold_high
type: float
default: 2.5
description: Ratio threshold for buy-side pressure alert
- name: alert_threshold_low
type: float
default: 0.4
description: Ratio threshold for sell-side pressure alert
lifecycle:
initTimeout: 10s
idleTimeout: 300s
maxRuntime: 86400s # Auto-restart daily for memory hygiene
The Function Interface Contract
Given the manifest above, the corresponding Python function must conform to a strict interface. The TickDB runtime uses a calling convention that injects the input stream and configuration as typed objects.
# pressure_monitor.py
import os
import time
import threading
from collections import deque
from dataclasses import dataclass
from typing import Iterator, Optional
@dataclass
class DepthSnapshot:
"""Represents a depth channel snapshot from TickDB."""
timestamp: int # Unix microseconds
symbol: str # Ticker symbol, e.g. "NVDA.US"
bids: list[tuple[float, float]] # [(price, size), ...]
asks: list[tuple[float, float]] # [(price, size), ...]
level: int # Depth level (1 = best, 3 = L3)
@dataclass
class PressureOutput:
"""Output schema for pressure_ratio events."""
timestamp: int
symbol: str
bid_pressure: float
ask_pressure: float
ratio: float
window_size: int
@dataclass
class AlertEvent:
"""Output schema for alert events."""
timestamp: int
symbol: str
trigger_type: str
ratio_before: float
ratio_after: float
class PressureMonitor:
"""
SKILL function: computes rolling-window buy/sell pressure ratio
from depth snapshots. Emits alerts on threshold crossings.
"""
def __init__(self, config: dict):
# Load configuration with env-var override support
self.window_seconds = int(
os.environ.get("PRESSURE_WINDOW_SECONDS", config.get("window_seconds", 60))
)
self.threshold_high = float(
os.environ.get("PRESSURE_THRESHOLD_HIGH", config.get("alert_threshold_high", 2.5))
)
self.threshold_low = float(
os.environ.get("PRESSURE_THRESHOLD_LOW", config.get("alert_threshold_low", 0.4))
)
# Rolling window: deque of (timestamp, pressure_snapshot)
self.window: deque = deque(maxlen=10000) # Safety cap on memory
self._lock = threading.Lock()
def compute_pressure(self, snapshot: DepthSnapshot) -> float:
"""
Computes instantaneous buy/sell pressure from a depth snapshot.
Buy pressure = sum of bid sizes at levels 1 through N
Sell pressure = sum of ask sizes at levels 1 through N
Ratio = buy_pressure / sell_pressure
"""
bid_total = sum(size for _, size in snapshot.bids)
ask_total = sum(size for _, size in snapshot.asks)
if ask_total == 0:
return float('inf') # No sell liquidity
return bid_total / ask_total
def prune_window(self, current_ts: int) -> None:
"""Removes stale entries outside the rolling window."""
cutoff = current_ts - (self.window_seconds * 1_000_000) # Convert to microseconds
while self.window and self.window[0][0] < cutoff:
self.window.popleft()
def run(
self,
inputs: Iterator[DepthSnapshot],
outputs: dict
) -> None:
"""
Main SKILL entry point. Receives depth snapshots, computes
rolling pressure metrics, and emits to configured output channels.
"""
last_alert_ratio: Optional[float] = None
last_output_ts = 0
for snapshot in inputs:
current_ts = snapshot.timestamp
# Prune expired entries
self.prune_window(current_ts)
# Compute instantaneous pressure
instant_pressure = self.compute_pressure(snapshot)
# Add to rolling window
with self._lock:
self.window.append((current_ts, instant_pressure))
# Compute window-average pressure
if len(self.window) < 2:
continue
window_avg = sum(p for _, p in self.window) / len(self.window)
# Emit pressure_ratio output (throttled to 1 Hz)
if current_ts - last_output_ts >= 1_000_000:
pressure_output = PressureOutput(
timestamp=current_ts,
symbol=snapshot.symbol,
bid_pressure=sum(s for _, s in snapshot.bids),
ask_pressure=sum(s for _, s in snapshot.asks),
ratio=window_avg,
window_size=len(self.window)
)
outputs["pressure_ratio"].emit(pressure_output)
last_output_ts = current_ts
# Emit alert on threshold crossing
if last_alert_ratio is not None:
crossed_high = (
last_alert_ratio < self.threshold_high
and window_avg >= self.threshold_high
)
crossed_low = (
last_alert_ratio > self.threshold_low
and window_avg <= self.threshold_low
)
if crossed_high or crossed_low:
alert = AlertEvent(
timestamp=current_ts,
symbol=snapshot.symbol,
trigger_type="threshold_cross",
ratio_before=last_alert_ratio,
ratio_after=window_avg
)
outputs["alert"].emit(alert)
last_alert_ratio = window_avg
# Export the SKILL entry point
def run(inputs: Iterator[DepthSnapshot], outputs: dict, config: dict) -> None:
"""
SKILL protocol entry point.
TickDB runtime injects: inputs (depth stream), outputs (channel writers), config (user params).
"""
monitor = PressureMonitor(config)
monitor.run(inputs, outputs)
Engineering Warnings for Production Deployment
The code above is production-grade, but several engineering considerations must be addressed before deployment.
# ⚠️ PRODUCTION CONSIDERATIONS
# 1. Memory hygiene: the rolling window deque has a maxlen of 10000.
# For symbols with high-frequency updates (>100 msg/sec),
# consider a sliding window with timestamp-based eviction instead of count-based.
# A 60-second window at 1000 msg/sec = 60,000 entries. Adjust maxlen accordingly.
# 2. Thread safety: the monitor uses a threading.Lock for window mutations.
# In async execution contexts, replace with asyncio.Lock or use a thread-safe
# queue-based architecture to avoid GIL contention.
# 3. Numeric stability: when ask_total is near zero, ratio returns inf.
# Handle this explicitly in production — consider capping at a max_ratio value
# and emitting a "liquidity_dry_up" alert instead.
# 4. Clock synchronization: the window uses snapshot.timestamp from TickDB.
# Ensure your TickDB server and SKILL runtime share a time source (NTP).
# Timestamp skew > 100ms will corrupt rolling window accuracy.
# 5. Backpressure: if outputs["pressure_ratio"].emit() blocks (e.g., downstream
# consumer is slow), the entire input loop stalls. For HFT workloads, use a
# non-blocking emit with a bounded output queue and drop-oldest policy.
Function Extension Patterns
The pressure monitor demonstrates a single-function SKILL. Enterprise deployments frequently require more sophisticated patterns.
Pattern 1: Multi-Symbol Correlation Engine
Deploy one SKILL function that subscribes to multiple symbols simultaneously and computes rolling correlations between their depth-derived metrics.
# correlation_engine.py
from collections import defaultdict
import statistics
class CorrelationEngine:
"""
SKILL function: computes rolling Pearson correlation between
two symbols' buy/sell pressure ratios.
Use case: detect cross-asset liquidity contagion (e.g., when
SPY pressure anomalies precede sector ETF moves).
"""
def __init__(self, config: dict):
self.symbol_a = config["symbol_a"]
self.symbol_b = config["symbol_b"]
self.window_bars = config.get("window_bars", 20)
self.correlation_threshold = config.get("correlation_threshold", 0.7)
# Separate rolling windows per symbol
self.windows: dict[str, list[float]] = defaultdict(list)
self.last_correlation: float = 0.0
def update_window(self, symbol: str, ratio: float) -> None:
"""Appends ratio to symbol's rolling window."""
window = self.windows[symbol]
window.append(ratio)
if len(window) > self.window_bars:
window.pop(0)
def compute_correlation(self) -> float:
"""Computes Pearson correlation between two windows."""
a = self.windows[self.symbol_a]
b = self.windows[self.symbol_b]
if len(a) < self.window_bars or len(b) < self.window_bars:
return 0.0
mean_a = statistics.mean(a)
mean_b = statistics.mean(b)
numerator = sum((x - mean_a) * (y - mean_b) for x, y in zip(a, b))
denom_a = sum((x - mean_a) ** 2 for x in a) ** 0.5
denom_b = sum((y - mean_b) ** 2 for y in b) ** 0.5
if denom_a == 0 or denom_b == 0:
return 0.0
return numerator / (denom_a * denom_b)
def run(self, inputs: Iterator, outputs: dict) -> None:
for event in inputs:
# Route event to appropriate symbol window
if event.symbol == self.symbol_a:
self.update_window(self.symbol_a, event.ratio)
elif event.symbol == self.symbol_b:
self.update_window(self.symbol_b, event.ratio)
else:
continue
# Recompute correlation whenever either window updates
if len(self.windows[self.symbol_a]) >= self.window_bars:
corr = self.compute_correlation()
if abs(corr) > self.correlation_threshold:
outputs["correlation_alert"].emit({
"timestamp": event.timestamp,
"symbol_pair": (self.symbol_a, self.symbol_b),
"correlation": corr,
"window_size": len(self.windows[self.symbol_a])
})
self.last_correlation = corr
Pattern 2: Stateful Event Sequencing
Some strategies require not just current state, but a sequence of state transitions. A SKILL function can maintain a finite state machine (FSM) tracking order book regime transitions.
# order_regime_fsm.py
from enum import Enum
class OrderRegime(Enum):
NORMAL = "normal"
IMBALANCE_BUILDING = "imbalance_building"
LIQUIDITY_VACUUM = "liquidity_vacuum"
SPRING_REVERSAL = "spring_reversal"
COLLAPSED = "collapsed"
class RegimeFSM:
"""
SKILL function: tracks order book regime transitions.
State machine logic:
NORMAL → IMBALANCE_BUILDING: pressure_ratio > 2.0 for 3+ consecutive updates
IMBALANCE_BUILDING → LIQUIDITY_VACUUM: spread widens > 3x baseline in < 2 sec
LIQUIDITY_VACUUM → SPRING_REVERSAL: spread contracts > 50% within 1 sec
Any state → COLLAPSED: bid or ask total drops below floor threshold
Use case: detect pre-earnings liquidity accumulation patterns for
event-driven entries.
"""
TRANSITION_RULES = {
OrderRegime.NORMAL: {
"imbalance_build": OrderRegime.IMBALANCE_BUILDING
},
OrderRegime.IMBALANCE_BUILDING: {
"spread_widen": OrderRegime.LIQUIDITY_VACUUM,
"reset": OrderRegime.NORMAL
},
OrderRegime.LIQUIDITY_VACUUM: {
"spread_contract": OrderRegime.SPRING_REVERSAL,
"collapse": OrderRegime.COLLAPSED
},
OrderRegime.SPRING_REVERSAL: {
"reset": OrderRegime.NORMAL,
"collapse": OrderRegime.COLLAPSED
},
OrderRegime.COLLAPSED: {
"recover": OrderRegime.NORMAL
}
}
def __init__(self, config: dict):
self.symbol = config["symbol"]
self.imbalance_count_threshold = config.get("imbalance_count", 3)
self.spread_widen_multiplier = config.get("spread_widen_multiplier", 3.0)
self.spread_contract_ratio = config.get("spread_contract_ratio", 0.5)
self.liquidity_floor = config.get("liquidity_floor", 500)
self.state = OrderRegime.NORMAL
self.imbalance_count = 0
self.baseline_spread: float | None = None
self.last_spread: float | None = None
def step(self, snapshot) -> tuple[OrderRegime, OrderRegime | None]:
"""
Advances the FSM by one tick. Returns (new_state, transition_event).
"""
bid_total = sum(s for _, s in snapshot.bids)
ask_total = sum(s for _, s in snapshot.asks)
spread = snapshot.asks[0][0] - snapshot.bids[0][0]
if self.baseline_spread is None:
self.baseline_spread = spread
prev_state = self.state
# Evaluate transition rules
if self.state == OrderRegime.NORMAL:
pressure = bid_total / max(ask_total, 1)
if pressure > 2.0:
self.imbalance_count += 1
if self.imbalance_count >= self.imbalance_count_threshold:
self.state = OrderRegime.IMBALANCE_BUILDING
return self.state, OrderRegime.IMBALANCE_BUILDING
elif self.state == OrderRegime.IMBALANCE_BUILDING:
if spread > self.baseline_spread * self.spread_widen_multiplier:
self.state = OrderRegime.LIQUIDITY_VACUUM
return self.state, OrderRegime.LIQUIDITY_VACUUM
elif snapshot.timestamp - getattr(self, 'last_update_ts', 0) > 5_000_000:
# No imbalance for 5 sec → reset
self.imbalance_count = 0
self.state = OrderRegime.NORMAL
elif self.state == OrderRegime.LIQUIDITY_VACUUM:
if self.last_spread and spread < self.last_spread * self.spread_contract_ratio:
self.state = OrderRegime.SPRING_REVERSAL
return self.state, OrderRegime.SPRING_REVERSAL
if bid_total < self.liquidity_floor or ask_total < self.liquidity_floor:
self.state = OrderRegime.COLLAPSED
return self.state, OrderRegime.COLLAPSED
elif self.state == OrderRegime.COLLAPSED:
if bid_total > self.liquidity_floor * 2 and ask_total > self.liquidity_floor * 2:
self.state = OrderRegime.NORMAL
self.baseline_spread = spread
self.imbalance_count = 0
return self.state, OrderRegime.RECOVER
self.last_spread = spread
self.last_update_ts = snapshot.timestamp
return self.state, None
Private Deployment Architecture
For enterprise clients operating in air-gapped environments — proprietary trading desks, regulated asset managers, sovereign wealth funds — cloud connectivity is not an option. TickDB supports fully private SKILL deployments.
Deployment Topology
┌─────────────────────────────────────────────────────────────┐
│ Enterprise Private Network │
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Market │ │ TickDB │ │ SKILL │ │
│ │ Data Feed │─────▶│ Core Engine│─────▶│ Runtime │ │
│ │ (Direct │ │ (Private │ │ (Isolated │ │
│ │ Exchange │ │ Install) │ │ Sandbox) │ │
│ │ Feed) │ │ │ │ │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
│ │ │ │
│ │ ┌─────────────┘ │
│ ▼ ▼ │
│ ┌─────────────┐ │
│ │ Custom │ │
│ │ Alert / │ │
│ │ Trading │ │
│ │ System │ │
│ └─────────────┘ │
└─────────────────────────────────────────────────────────────┘
Private Installation Requirements
| Component | Minimum Specification | Recommended |
|---|---|---|
| CPU | 8 cores | 16+ cores (for multi-symbol SKILL parallelism) |
| Memory | 16 GB RAM | 32 GB RAM |
| Storage | 500 GB SSD | 1 TB NVMe SSD (for order book replay) |
| Network | 1 Gbps | 10 Gbps (for high-frequency symbol feeds) |
| OS | Ubuntu 22.04 LTS / RHEL 9 | Same |
| Kernel | Linux 5.15+ | Linux 6.x (for io_uring low-latency I/O) |
Installing a Custom SKILL in Private Mode
Private deployments use an offline SKILL installation process. The workflow differs from cloud deployment in two ways: images are loaded from a local registry or tarball, and all configuration is managed through a local YAML file rather than a cloud dashboard.
# Step 1: Transfer SKILL package to air-gapped environment
# The package is a signed .tar.gz containing the function code and manifest
$ scp order-pressure-monitor-1.2.0-skill.tar.gz deploy@private-tickdb:/opt/tickdb/skills/
# Step 2: Import the SKILL into the local registry
$ tickdb skill import /opt/tickdb/skills/order-pressure-monitor-1.2.0-skill.tar.gz \
--registry-url file:///opt/tickdb/local-registry \
--verify-signature
# Step 3: Register symbols for depth subscription
$ tickdb symbol register --config /opt/tickdb/etc/symbols.yaml
# symbols.yaml example:
# symbols:
# - symbol: NVDA.US
# enabled: true
# channels: [depth]
# - symbol: TSLA.US
# enabled: true
# channels: [depth]
# - symbol: SPY.US
# enabled: true
# channels: [depth, kline]
Configuration File for Private SKILL Execution
# /opt/tickdb/etc/skill-config.yaml
apiVersion: tickdb.io/v1
kind: SkillDeployment
metadata:
name: order-pressure-monitor-production
namespace: enterprise-desk-01
spec:
skill:
name: order-pressure-monitor
version: "1.2.0"
registry: file:///opt/tickdb/local-registry
symbols:
- NVDA.US
- TSLA.US
- SPY.US
- QQQ.US
runtime:
executionMode: streaming # streaming | batch
parallelism: 2 # Number of concurrent symbol processors
memoryLimit: 512Mi # Per-symbol process limit
cpuAffinity: [0, 1] # Pin to specific cores for latency isolation
outputs:
pressure_ratio:
destination: mqtt
broker: mqtt://internal-broker:1883
topic: tickdb/pressure/{symbol}
qos: 1
alert:
destination: webhook
endpoint: https://internal-alerting.svc/regime-alerts
auth:
type: hmac
secretRef: /opt/tickdb/secrets/alert-hmac.key
retryPolicy:
maxRetries: 3
backoffMultiplier: 2
timeout: 5s
config:
window_seconds: 60
alert_threshold_high: 2.5
alert_threshold_low: 0.4
# Environment variable overrides
envOverrides:
- name: PRESSURE_THRESHOLD_HIGH
value: "2.5"
- name: LOG_LEVEL
value: "INFO"
healthCheck:
enabled: true
interval: 30s
failureThreshold: 3
endpoint: http://localhost:9090/health
lifecycle:
autoRestart: true
maxRestartsPerHour: 4
gracefulShutdownTimeout: 30s
Starting and Monitoring the SKILL
# Deploy the SKILL
$ tickdb skill deploy --file /opt/tickdb/etc/skill-config.yaml --dry-run
# Apply
$ tickdb skill apply --file /opt/tickdb/etc/skill-config.yaml
# Monitor runtime status
$ tickdb skill status order-pressure-monitor-production
# Expected output:
# NAME STATUS RESTARTS AGE MEMORY CPU
# order-pressure-monitor-production Running 0 2h 312Mi 0.38
#
# Per-symbol streams:
# NVDA.US ▶ pressure_ratio (0.42 Hz avg) ▶ alert (0 events)
# TSLA.US ▶ pressure_ratio (0.38 Hz avg) ▶ alert (1 event @ 14:32:01)
# SPY.US ▶ pressure_ratio (0.51 Hz avg) ▶ alert (0 events)
# QQQ.US ▶ pressure_ratio (0.44 Hz avg) ▶ alert (0 events)
# Stream live logs
$ tickdb skill logs order-pressure-monitor-production --follow --tail 50
# Inspect output payload samples
$ tickdb skill inspect order-pressure-monitor-production \
--output pressure_ratio \
--symbol NVDA.US \
--limit 5
# Expected payload sample:
# {
# "timestamp": 1744327681000000,
# "symbol": "NVDA.US",
# "bid_pressure": 28450.0,
# "ask_pressure": 19300.0,
# "ratio": 1.474,
# "window_size": 42
# }
Enterprise Use Case: Pre-Earnings Liquidity Regime Detection
To ground the technical content in a concrete enterprise scenario, consider the following deployment.
A quantitative event-driven desk at a mid-sized asset manager wants to identify pre-earnings liquidity accumulation patterns across a basket of 30 large-cap tech names. Their existing system receives TickDB depth feeds but lacks the ability to:
- Detect when a symbol transitions from "normal" to "imbalance building" regime.
- Alert the trading system when a liquidity vacuum forms within 30 seconds of the earnings release timestamp.
- Record the full regime transition sequence for post-event analysis.
Solution: Deploy the order-regime-fsm SKILL across all 30 symbols. Configure the SKILL to emit regime transition events to an internal Kafka topic. The trading system consumes this topic and places conditional orders based on the detected regime.
# Pre-earnings deployment config
spec:
skill:
name: order-regime-fsm
version: "1.0.0"
symbols:
- NVDA.US
- MSFT.US
- GOOGL.US
- META.US
- AMD.US
# ... 25 more symbols
outputs:
regime_transition:
destination: kafka
brokers:
- kafka.internal:9092
topic: earnings-regime-transitions
serializer: avro
schemaRegistry: http://schema-registry.internal:8081
config:
imbalance_count: 3
spread_widen_multiplier: 3.0
spread_contract_ratio: 0.5
liquidity_floor: 500
event_window_before_earnings: 300 # Track 5 minutes pre-release
The engineering team reports: average detection latency from tick receipt to regime event emission is 4.2 milliseconds, measured at the Kafka producer. This latency is deterministic — the FSM processes each snapshot in a single pass with no external dependencies. The trading system receives the regime transition alert before the next tick arrives.
SKILL Security Model
Enterprise deployments require a security model that governs what a SKILL can and cannot access.
| Permission | Description | Default |
|---|---|---|
depth:read |
Read order book depth data | Granted |
kline:read |
Read OHLCV candle data | Granted |
trades:read |
Read trade tape | Granted |
network:outbound |
Make outbound HTTP/WebSocket calls | Denied (private) / Restricted (cloud) |
filesystem:read |
Read from disk | Denied |
filesystem:write |
Write to disk | Denied |
env:read |
Read environment variables | Restricted (secrets via secretRef only) |
exec:spawn |
Spawn subprocesses | Denied |
For private deployments, all permissions are locked down by default and explicitly granted in the deployment manifest. For cloud deployments, outbound network calls require an explicit allowlist of destination domains.
Building Your First Custom SKILL: A Step-by-Step Checklist
If you are building a custom SKILL for the first time, follow this checklist to ensure production readiness.
| Step | Task | Verification |
|---|---|---|
| 1 | Define the business problem in one sentence | "This SKILL detects [specific condition] so that [specific system] can [take specific action]." |
| 2 | Design the input/output schema in skill.yaml |
Schema validated against TickDB runtime schema validator |
| 3 | Implement the function with full error handling | Every code path has a fallback; no unhandled exceptions |
| 4 | Add heartbeat and timeout wrappers | Function terminates gracefully on idle timeout |
| 5 | Add engineering warning comments | At least one warning comment per 50 lines of code |
| 6 | Load secrets via secretRef or environment variables |
No hardcoded credentials in function code |
| 7 | Write unit tests covering nominal and edge cases | Test coverage ≥ 80% |
| 8 | Package as a signed .tar.gz |
Signature verified during import |
| 9 | Deploy to staging with dry-run enabled | Confirm outputs match expected schema |
| 10 | Load test with 3x expected message rate | Monitor memory growth over 1-hour sustained load |
| 11 | Enable health check endpoint | /health returns 200 OK when function is healthy |
| 12 | Document deployment configuration | The skill-config.yaml is self-documenting |
| 13 | Hand off to operations with runbook | Runbook covers: start, stop, restart, log inspection, metric reference |
Next Steps
If you are an enterprise quant team evaluating air-gapped TickDB deployment, contact enterprise@tickdb.ai to discuss your infrastructure requirements and receive a private deployment assessment.
If you want to build a custom SKILL on the cloud platform:
- Review the full SKILL protocol specification in the TickDB documentation portal
- Download the SKILL SDK (
pip install tickdb-skill-sdk) - Clone the example repository (
tickdb/examples/skill-templates) for reference implementations - Sign up at tickdb.ai to access the SKILL marketplace and deployment dashboard
If you are an AI tooling developer, search for the tickdb-market-data SKILL in your AI tool's marketplace. It provides a function-calling interface to TickDB market data that can be used to build AI agents with real-time market awareness.
If you are an individual quant trader interested in customizing your own market data logic, the free tier includes SKILL development sandbox access with limited symbol scope. Upgrade to the Professional plan for full symbol coverage and private SKILL deployment support.
This article does not constitute investment advice. Market data analysis and algorithmic trading involve risk; backtested results do not guarantee future performance. SKILL deployments in production trading systems should be validated through paper trading and thorough risk review before capital deployment.