TessTrade Documentation
website·Indexed 30 days ago
https://learn.tesstrade.comDeveloper guides and SDK reference for building trading strategies and custom indicators using Python. Includes documentation on the script lifecycle, the main() dispatcher, the DECLARATION shape, and the SDK for managing positions, orders, and candles. Covers both backtesting and live paper trading bots, as well as declarative mode for entry and exit conditions.
What's inside TessTrade
- A paper bot is a Python script that executes continuously on the backend, independent of an open browser tab. It consumes live data, executes a strategy, and records orders in a simulated account database. Unlike the live editor, which requires an active session, paper bots persist until manually stopped.
Understand the difference between Backtest and Chart Trading
TessTrade allows the same Python script (using the
main(df, sdk, params)contract) to be run in two distinct contexts. The primary difference is how data is delivered and how orders are executed.Feature Backtest Chart Trading Data Full history pre-loaded Live stream candle by candle Execution time Minutes (processes thousands of candles) Indefinite (runs while enabled) Orders Simulated against history Simulated against a paper trading account Slippage/fees Configurable in the panel Real from the connected exchange order book Result Final snapshot with metrics Evolving orders and equity Typical use Validate ideas and optimize parameters Operate paper trading in real time Understand the Tesstrade script execution lifecycle
The engine executes scripts in a specific sequence of phases to ensure security and correct state management:
- Validation: The engine checks the code against sandbox limits. If it fails, a
SecurityErroris raised and the code never runs. - Loading: The script is run once at the top level. Root-level definitions, global variables, and statements are registered and executed.
- Entrypoint Discovery: The engine looks for a valid entrypoint in this priority order:
main(),on_bar(sdk), event hooks (on_trade_tick,on_quote_tick,on_book_update), or aStrategyclass. - Metadata Retrieval: The engine calls
main()with no arguments to retrieve theDECLARATIONobject, which defines UI parameters and chart plots. - Per-candle Loop: For every closed candle, the engine updates
sdk.candlesand calls the entrypoint (e.g.,main(sdk=sdk, params=params)). - Plots Phase: For backtests or chart loading, the engine calls
main(df=pandas_dataframe, params=params)to retrieve plot and series data.
- Validation: The engine checks the code against sandbox limits. If it fails, a
Interpret the TessTrade backtest results panel
After a backtest, TessTrade provides a results panel divided into five main sections to evaluate strategy performance:
- Summary: Quantitative metrics such as Sharpe ratio, drawdown, and profit factor.
- Equity Curve: A capital chart showing the evolution of total capital over time.
- Trades: A detailed list of every round-trip trade (entry and exit).
- Distribution: A histogram of gains and losses per trade.
- Logs: The standard output (
stdout) from the strategy script.
Handle Python RuntimeErrors in scripts
Classic Python exceptions not handled by the script are wrapped in aRuntimeError. Common causes include false assumptions about data availability, division by zero, or missing keys in candle data.# Fix IndexError: Validate candle length if len(sdk.candles) < 20: return sma = sum(c["close"] for c in sdk.candles[-20:]) / 20 # Fix ZeroDivisionError: Check divisor if avg_loss == 0: return 100.0 rs = avg_gain / avg_loss # Fix KeyError: Use .get() with a default vol = sdk.candles[-1].get("volume", 0.0)Use the Chart Trading Code Editor for live Python scripts
The Code Editor allows developers to write and activate Python scripts that remain coupled to live data on a real-time chart. To open the editor, click the Editor icon in the Chart Trading panel. The environment includes a code editing area with syntax highlighting, action buttons (Run, Save, Open Docs), a parameters panel for DECLARATION inputs, and output tabs for signals, logs, and errors.Use full-series indicators in _build_chart
The_build_chartfunction runs only once during initialization. Therefore, it is safe and correct to callIndicatormethods over the entire DataFrame without worrying about the O(1) rule.def _build_chart(df, params): period = int((params or {}).get("period", 14)) return {**DECLARATION, "series": {"rsi": Indicator.rsi(df, period)}}Determine when to use Backtest vs Chart Trading
Choose the execution context based on your current development goal:
Use Backtest when:
- Validating a new strategy idea quickly.
- Optimizing parameters (e.g., testing different SMA periods) to find the best Sharpe ratio.
- Generating quantitative metrics like drawdown, profit factor, and win rate.
- Testing against several years of historical data in seconds.
- Comparing multiple versions of a strategy over the same period.
Use Chart Trading when:
- A strategy is validated in backtest and needs observation in a live environment before using real capital.
- Testing robustness against live data streams (checking for latency, gaps, or late trades).
- Validating if a strategy performs under the current market regime.
- The strategy relies on precise intraday timing via
sdk.candles[-1]["time"].
Calculate indicators efficiently using the Indicator global
TheIndicatorglobal provides native, optimized math for common indicators. To maintain O(1) performance per bar and avoid performance degradation as history grows, always callIndicatormethods over a bounded window (e.g.,sdk.candles[-N:]) rather than the entire history. Note thatimport tesstrade_indicatorsis forbidden and will be rejected by the validator.LOOKBACK = 300 # Fixed window to ensure O(1) complexity def on_bar_strategy(sdk, params): if len(sdk.candles) < 15: return # Use a bounded slice of candles rows = sdk.candles[-LOOKBACK:] rsi = Indicator.rsi(rows, 14)[-1] if rsi is not None and rsi < 30: sdk.buy(action="buy_to_open", qty=1, order_type="market")Custom Indicator Implementation Checklist
Ensure your custom indicator meets these requirements before deployment:
- Colors and parameter defaults are defined as top-of-file constants.
- All tunable values (numbers and colors) are declared as
inputs. -
type:"color"inputs are read fromparamsand manually injected into the plot'scolorfield. - Plot colors use
#RRGGBBformat (no alpha channel); usewidthinstead oflineWidth. - Math uses the pre-injected
Indicatorglobal (do not useimport tesstrade_indicators). - All
seriesarrays are exactlylen(df)long, usingNonefor warm-up. -
paneandscalesettings match the indicator's value range. - The
df=branch returns the DECLARATION (including colors) and theseriesdata.
Stop a Paper Trading Bot and handle positions
Clicking Stop sends a signal to the backend to terminate the sandbox and discard
sdk.state. The script will not be called for subsequent candles.Important: Open positions are NOT automatically closed when a bot is stopped. You must either close positions manually via the UI before stopping or implement a shutdown check in your script (though the current SDK does not provide a native
_should_stophook, manual closure is recommended).Execute orders using canonical actions
Every order in the SDK is issued viasdk.buy(),sdk.sell(), orsdk.close(). To ensure auditability and preventProtocolError, an explicitactionmust be provided as a keyword argument forbuy()andsell(). Whilesdk.close()defaults toclose_position, using explicit actions is the recommended idiom.