Appearance
TessTrade Python SDK
Write indicators and strategies in Python. The same script runs in two contexts - a historical backtest and live chart trading - under an identical contract. This documentation covers how the engine calls your code, what the SDK exposes, the set of accepted actions, and the most common pitfalls.
INFO
New here? Start with Backtest vs Chart Trading for the mental model, then jump to the Example script to write your first strategy in five minutes.
What you write
A Python file with a main(df, sdk, params) function and, optionally, a DECLARATION dictionary describing the editable parameters and the chart plots.
python
DECLARATION = {
"type": "strategy",
"inputs": [
{"name": "fast_period", "type": "int", "default": 9, "min": 1, "max": 100},
{"name": "slow_period", "type": "int", "default": 21, "min": 2, "max": 200},
],
}
def main(df=None, sdk=None, params={}):
params = params or {}
if sdk is not None:
# tick by tick / candle by candle execution
return on_bar_strategy(sdk, params)
if df is not None:
# chart plots
return _build_chart(df, params)
return DECLARATIONThe same function is called in three different contexts. See The main() dispatcher for details on each one.
Documentation map
Getting started
| Page | Description |
|---|---|
| Backtest vs Chart Trading | The two execution contexts and why the same script runs in both |
| Example script | A minimal runnable strategy to verify the editor and the pipeline |
| Sandbox limits | Available modules, builtins, and resource caps |
Contract
| Page | Description |
|---|---|
The main() dispatcher | The three contexts the engine calls your script in |
The DECLARATION shape | Root-level dictionary for inputs, plots, and conditions |
| Script lifecycle | How the engine loads, validates, and executes your code |
SDK reference
| Page | Description |
|---|---|
| Candles, params and state | Reading market data and persisting values across bars |
| Position, cash and equity | Portfolio properties exposed on the SDK |
| Canonical actions | Every action string the engine accepts |
| Order types | Market, limit, stop, stop-limit, bracket |
| Stops, targets and trailing | Protective stops, take-profit, and trailing stops |
Indicators
| Page | Description |
|---|---|
Plots and series | How chart plots are declared and rendered |
| Implementing SMA and EMA | Moving average recipes in pure Python |
| RSI, MACD and Bollinger Bands | Pure-Python implementations of the three most common oscillators |
| Panes: overlay vs new pane | When to overlay on price versus use a separate pane |
Ready-to-use strategies
| Page | Description |
|---|---|
| SMA Crossover | Dual moving-average trend-following template |
| RSI Mean Reversion | Overbought/oversold reversal template |
| MACD Momentum | Signal-line crossover template |
| Persistent state and trailing stop | Patterns for sdk.state and trailing exits |
| Solid entry/exit patterns | Checklist of robust practices |
Declarative mode
| Page | Description |
|---|---|
| When to use entry/exit conditions | Declarative versus imperative mode and how to choose |
| Supported operators | Operator catalog with semantics |
Backtest
| Page | Description |
|---|---|
| Reading the results | Interpreting the output panel |
| Performance metrics | Sharpe, drawdown, profit factor, and which ones actually matter |
| Troubleshooting | Common failure modes with root cause and fix |
Chart Trading
| Page | Description |
|---|---|
| Live editor | In-chart development environment |
| Paper Trading Bots | Persistent simulated bots that run without an open tab |
| Live vs backtest differences | Subtle execution gaps between the two contexts |
Reference
| Page | Description |
|---|---|
| Canonical actions table | Quick lookup for every accepted action |
| Operators table | Quick lookup for declarative operators |
| Error catalog | Every exception the engine can raise and how to fix it |
| Glossary | Term definitions |
What the SDK provides
sdk.candles- list of OHLCV candles.sdk.params- the parameters defined inDECLARATION["inputs"], already typed.sdk.state- dictionary persistent across candles (useful for trailing stops, flags, cooldowns).sdk.position- current net position (positive = long, negative = short, zero = flat).sdk.cash,sdk.equity,sdk.buy_price,sdk.sell_price- portfolio snapshot.sdk.buy(...),sdk.sell(...),sdk.close(...),sdk.update_exits(...)- issue signals.
Full API in SDK reference.
Sandbox
Scripts run in a hardened Python sandbox. Available resources:
- Injected modules (no
importrequired):np(numpy),pd(pandas),math,json,datetime, plus safe optimized versions ofta,pandas_ta, andtalib. - Allowed builtins:
len,range,sum,abs,min,max,round,sorted,zip,enumerate,isinstance,int,float,str,list,dict,tuple,set,print. - Exception classes:
ValueError,TypeError,KeyError,IndexError,RuntimeError,ZeroDivisionError,OverflowError.
Anything outside this surface raises SecurityError. Full detail in Sandbox limits.
Execution limits
| Limit | Default | Raised if exceeded |
|---|---|---|
| Time per call | 200ms | TimeoutError |
| Memory | 64MB | MemoryError |
| Code size | ~100KB | rejected at load time |
| Nesting depth | 20 levels | rejected at load time |
TIP
Quick start: copy the SMA Crossover template, adjust the parameters, and run it. From there, swap in the indicator of your choice from Implementing SMA and EMA or RSI, MACD and Bollinger Bands.