Developer docs
Build trading bots for SteraTrader
The SteraTrader Add-Ons SDK reference: bot lifecycle, trading actions, parameters, allowed imports, backtesting, packaging, review and selling. SDK version 0.1.
Overview
An add-on is a Python package built on the stera SDK. There are three kinds: trading bots that open and close positions, trade tools that manage positions a trader opened (trailing, breakeven, risk sizing), and indicators.
You build and backtest on your own computer. You upload the package, where it gets instant automatic checks and a human review. Approved add-ons are listed in the marketplace and run in the SteraTrader cloud. Your source code never leaves SteraTrader: traders get running instances, never files.
Quick start
python3 -m venv stera-env && . stera-env/bin/activate
pip install https://steratrader.com/downloads/stera_sdk-0.1.0-py3-none-any.whl
# start from the example
curl -LO https://steratrader.com/downloads/gold-breakout-example.zip
unzip gold-breakout-example.zip -d gold_breakout
# download prices from the developer portal, then:
stera backtest ./gold_breakout --data XAUUSD_M15_30d.csv --symbol XAUUSD --contract 100 --spread 0.30
stera package ./gold_breakoutCreate a free account in the developer portal to download historical prices and upload add-ons.
Project layout
gold_breakout/
├── addon.json # manifest
├── bot.py # entry file with your Bot class
├── signals.py # optional: your own helper modules
└── README.md # optional{
"name": "Gold Breakout",
"version": "1.0.0",
"entry": "bot.py",
"class": "GoldBreakout",
"sdk": ">=0.1",
"requirements": []
}| Field | Required | Meaning |
|---|---|---|
| name | yes | Display name. |
| version | yes | Three numbers, like 1.0.0. Must match the version you enter when uploading, and each upload needs a new version. |
| entry | yes | The file that defines your bot class. |
| class | yes | Your class name. It must subclass Bot and define on_bar or on_tick. |
| sdk | no | The SDK versions you support, e.g. >=0.1. |
| requirements | no | Extra packages. Only numpy and pandas are allowed. |
Bot lifecycle
Subclass Bot and implement the hooks you need. The platform calls them; you never call them yourself.
from stera import Bot, Param
class GoldBreakout(Bot):
"""Buys a close above the previous N-bar high."""
symbol = Param("XAUUSD", help="Instrument to trade")
lots = Param(0.10, min=0.01, max=5, help="Size of each trade")
lookback = Param(20, min=5, max=200, help="Bars in the breakout range")
stop = Param(8.0, min=0.5, help="Stop distance in price")
target = Param(16.0, min=0.5, help="Target distance in price")
def on_start(self):
self.log(f"starting on {self.symbol} with {self.lots} lots")
def on_bar(self, bar):
if self.positions or len(self.history(self.lookback + 1)) <= self.lookback:
return
if bar.close > self.highest(self.lookback):
self.buy(self.symbol, self.lots,
sl=bar.close - self.stop, tp=bar.close + self.target)
def on_fill(self, fill):
if fill.reason != "open":
self.log(f"{fill.reason}: {fill.profit:+.2f}")| Hook | When it runs |
|---|---|
| on_start() | Once, before the first bar. Settings are already validated. |
| on_bar(bar) | Once for every completed bar. Most strategies live here. bar is a Bar. |
| on_tick(bid, ask) | On every price update, in the cloud. Backtests replay bars, so on_tick is not called during a backtest. |
| on_fill(fill) | After a position opens or closes, for any reason (your close, stop loss, take profit). fill is a Fill. |
| on_stop() | Once, when the bot is stopped or the backtest ends. |
Trading actions
| Method | What it does |
|---|---|
| buy(symbol, lots, sl=None, tp=None) | Opens a buy at market. sl and tp are absolute prices, not distances. |
| sell(symbol, lots, sl=None, tp=None) | Opens a sell at market. |
| close(position) | Closes one position from self.positions. |
| close_all() | Closes every position this bot holds. |
Orders are market orders. Buys fill at the ask and sells at the bid. In the cloud, platform limits apply to every order (see Running in the cloud). An order over a limit is refused and logged; it never partly fills.
Account and market state
| Member | Returns |
|---|---|
| self.positions | This bot's open positions, a list of Position. |
| self.balance | Account balance. |
| self.history(n) | The last n bars, the current bar last. |
| self.highest(n, field="high") | Highest value over the n bars before the current one. |
| self.lowest(n, field="low") | Lowest value over the n bars before the current one. |
| self.sma(n, field="close") | Simple average over the last n bars including the current one, or None until there are n bars. |
| self.log(message) | Writes to the bot's log: your terminal in backtests, the instance log in the cloud. |
| self.<setting> | The value of any Param, as the trader set it. |
Data types
| Type | Fields |
|---|---|
| Bar | time, open, high, low, close, volume. Prices are bid prices. |
| Fill | position_id, symbol, side, lots, price, time, reason, profit. reason is one of open, close, stop_loss, take_profit, end_of_test. profit is 0 on open. |
| Position | id, symbol, side (buy or sell), lots, open_price, open_time, sl, tp. |
Parameters
A Param is a setting the trader can change when starting your add-on. Declare it on the class. The type comes from the default value.
lots = Param(0.10, min=0.01, max=5, help="Size of each trade") # float
lookback = Param(20, min=5, max=200) # int
symbol = Param("EURUSD") # str
trail = Param(False, help="Trail the stop") # bool| Argument | Meaning |
|---|---|
| default | The starting value. Its type (int, float, str or bool) is the setting's type. |
| min / max | Optional numeric limits. Values outside them are refused when the bot starts. |
| help | One line shown to traders next to the setting. |
Values are converted to the setting's type and checked before on_start. An unknown setting name, a wrong type or a value out of range stops the bot with a clear message instead of trading on bad input. Your settings, defaults and ranges are listed automatically on your marketplace page, read straight from your code. In backtests, set them with --param name=value.
What your code can use
Add-ons run in a sealed sandbox. They receive prices and send orders through the SDK, and nothing else. Uploads are checked for these rules before review, and the sandbox enforces them again at run time.
| Rule | |
|---|---|
| Imports allowed | stera, math, statistics, datetime, collections, itertools, functools, dataclasses, typing, decimal, enum, random, numpy, pandas, and your own modules in the package. |
| Not allowed | os, sys, subprocess, socket, network libraries, file access, threads and anything else not listed above. |
| Calls not allowed | eval, exec, compile, __import__, open, input, globals, locals, vars, breakpoint, getattr, setattr, delattr. |
| Attributes | No double-underscore attributes such as __class__, except __init__ and __name__. |
| Package | A .zip up to 5 MB, 20 MB unpacked, at most 200 files, only .py, .json, .txt, .md and .csv. |
Backtesting
Download bars for any symbol and timeframe from the developer portal: the same prices SteraTrader brokers trade on. Any CSV with time, open, high, low, close columns (and optionally volume) also works.
| Flag | Meaning |
|---|---|
| --data | CSV of bars (required). |
| --symbol | Symbol the data is for (required). Orders on other symbols are refused. |
| --balance | Starting balance. Default 10000. |
| --spread | Spread in price units, e.g. 0.30 for gold or 0.00010 for EURUSD. Default 0. |
| --contract | Contract size: 100 for gold, 100000 for FX majors. Default 100000. |
| --commission | Commission per lot, round turn. Default 0. |
| --param name=value | Override a setting. Repeatable. |
| --logs N | Print the last N log lines. |
| --json | Print the report as JSON. |
How fills are modelled, on purpose on the cautious side: an order placed during a bar fills at the next bar's open, never at the close that triggered it. When one bar touches both your stop and your target, the stop counts first. Positions still open at the end are closed at the last price. The report shows net profit, return, trade count, win rate, profit factor and maximum drawdown.
Packaging and upload
stera package ./gold_breakout # → gold_breakout/dist/gold-breakout-1.0.0.zipIn the developer portal, create the add-on once, then upload each version with a short note on what changed. Checks run immediately.
Checks and review
| Check | What it confirms |
|---|---|
| files | Allowed file types, safe paths, at most 200 files. |
| size | Unpacked size within 20 MB. |
| manifest | addon.json is valid and complete, and requirements are allowed. |
| code | Every file parses, and imports and calls follow the rules above. Failures give the exact file and line. |
| entry | The class exists, subclasses Bot and defines on_bar or on_tick. |
| version | The upload version matches addon.json. |
Versions that pass go to SteraTrader review. Reviewers read the code and check that it does what the description says. They reject hidden behaviour, obfuscation, and undisclosed martingale or grid position sizing. A rejection always comes with a note. Approved versions appear in the marketplace. Automatic backtests across several symbols and timeframes will also run on every uploadcoming soon
Running in the cloudcoming soon
Approved add-ons run in isolated sandboxes on SteraTrader's own servers, next to the market, with no VPS. Traders start them from their terminal on their own accounts. Every running instance has limits enforced by the platform, not by your code:
| Limit | Effect |
|---|---|
| Maximum lots | Orders above it are refused. |
| Maximum daily loss | When reached, the instance pauses for the rest of the day. |
| Orders per minute | Protects against runaway loops. Over it, orders are refused and the instance pauses. |
| Trade-only access | Add-ons can trade. They can never deposit, withdraw or change account settings. |
| Demo first | Brokers decide whether add-ons may run on live accounts at all. |
| Kill switch | The trader, their broker and SteraTrader can each stop any instance instantly. |
Selling
Listings can be free, a one-time price or a monthly subscription, with an optional free trial of up to 30 days on a demo account. Paid listings require identity verification. Because add-ons only run in the cloud, there is no copy protection to build and no piracy: buyers get running instances, never your files. Payments, payouts and the revenue share are published before paid sales opencoming soon
Your listing must describe honestly what the add-on trades and how. It may not promise profits, and any backtest you quote must be reproducible with the SDK. Live performance on your marketplace page is measured by SteraTrader and cannot be edited.
FAQ
Can I use my own indicators? Yes. Put helper modules in your package and import them, or compute with numpy and pandas.
Can my bot call an external API or signal service? No. Add-ons have no network access, which keeps traders' accounts and your bot's behaviour predictable and reviewable.
Can I trade several symbols? In the cloud, yes. A local backtest uses one data file, so it tests one symbol at a time.
Who sees my code? SteraTrader reviewers, to approve it. Nobody else: not traders and not brokers.
Ready to build?
Create a developer account, download prices and upload your first add-on.
Open the developer portal