For developers

Write your own
strategy in Rust

The SDK, the command line and the backtest engine behind tradectl. Build a strategy, test it on real data, and run it live.

Install the CLI in one line

One curl, no package manager. This installs the tradectl command-line engine that runs your bots. The desktop Lab is a separate download. The script finds your OS and CPU, downloads the matching binary, checks its SHA256 and installs it in ~/.tradectl/bin. If that folder is not on your PATH, it prints the line to add.

terminal
$ curl -fsSL https://tradectl.com/install.sh | sh
Linux x86_64 Linux aarch64 macOS Intel macOS Apple Silicon
quick start
# Sign in with an API key from your tradectl.com account (to install strategies and use your plan)
$tradectl login
# Start a strategy project and build it
$tradectl init dip-buyer && cd dip-buyer
$tradectl build
# Record market data for a few days, then pack it into one file
$tradectl collect binance -p BTCUSDT --all-streams -o data/market
$tradectl prepare --root data/market --symbol BTCUSDT --interval "2026-10-*" -o data/btc.bin
# Backtest it, then search the parameters
$tradectl backtest --data data/btc.bin -p dip=0.5 -p tp=0.3
$tradectl sweep --data data/btc.bin -r dip=0.2:1.0:0.1 -r tp=0.2:0.6:0.1
# Run it as a bot. The config has "isEmulator": true, so it trades on paper
$tradectl run my-bot -c config.json
# Go live: add your exchange keys, set "isEmulator": false, run in the background
$tradectl auth set binance
$tradectl run my-bot -c config.json --daemon
$tradectl stop my-bot
# Or install a ready strategy
$tradectl install shot

Everything you need
to trade smarter

Each card is a command of the tradectl CLI, plus the desktop Lab.

01

Run bots

Run your strategy as a bot on Binance futures: tradectl run my-bot -c config.json. Paper or live is one switch in the config.

  • --daemon runs the bot in the background
  • tradectl stop cancels the bot's orders and closes its positions
  • tradectl status and tradectl logs show what it is doing
02

Write a strategy

tradectl init makes a Rust project on the SDK; tradectl build compiles it into a plugin the bot loads.

03

Market data

tradectl collect records ticker, trades, candles and order book from Binance; tradectl prepare packs the days into one file.

04

Backtest and sweep

Test the same strategy code on recorded data before it trades.

  • tradectl backtest simulates fills with maker and taker fees
  • tradectl sweep -r key=min:max:step tries every combination of parameters and ranks them
  • Results are saved, so the desktop Lab can show them
05

Keep it running

tradectl service install makes a bot a Linux service, tradectl autostart on starts bots after a restart, and tradectl telegram link sends alerts to Telegram.

06

Watchdog

tradectl watchdog is a separate guard, best on another machine, that watches your bots and your exchange account for positions left without protection.

07

Account and strategies

tradectl login and tradectl license for your plan, tradectl auth set for exchange keys, tradectl install for a ready strategy (SHA256 checked), tradectl update for a new CLI.

08

The Lab

A desktop app for macOS, Windows and Linux to watch and control your bots: positions, orders and trades on a live chart, settings, pausing or restarting a strategy, backtests and sweeps. It connects straight to your bot over a secure port. Download the Lab →

What the engine
handles for you

You write the trading logic. The engine does the work that makes a live bot safe, the same in paper and live.

01

Order lifecycle

You say what orders you want; the engine places, amends and cancels them, follows every fill and keeps your take-profit and stop-loss in step with the position.

  • Take-profit and stop-loss sized to what really filled
  • Change one exit by its id; the others stay as they are
  • Orders the exchange refuses are handled for you
  • Exit delay, and a virtual stop-loss the engine watches itself
02

Clean stops

A stop leaves the bot flat: it cancels the bot's orders, closes its positions and checks the exchange for anything left.

  • tradectl stop and Ctrl-C both close out the bot
  • Each close is booked as a trade
  • Then the bot's symbols are checked on the exchange for leftover orders and positions
03

Risk controls

Limits from your config are checked before any order goes out. When a limit trips, new entries stop and open positions are still managed to the end.

  • Sessions that pause entries and change order size
  • Cooldowns between entries and after a position closes
  • A maximum loss per hour for the whole bot
  • Repeated exchange errors pause or stop one strategy, not the whole bot
04

Exchange

Your strategy never calls an exchange API: the engine carries out its orders through one exchange interface, so the same code is meant to run on many exchanges.

  • Binance at launch, more to come
  • The engine keeps you inside the exchange's rate limits
  • Exits and stops are never held back by those limits
05

Many strategies, one bot

Run several strategies in one process, even on the same symbol.

  • Pause, resume or restart one strategy without touching the others
  • Strategies declare the indicators they need; the engine computes and shares them
  • Every config change is saved as a version you can view and restore
06

Operations

What you need to leave a bot running.

  • Paper mode and backtests run the same strategy code as live
  • Every trade is kept in a local database
  • Telegram alerts, and a crash report sent to you
  • Memory and disk guards
  • The desktop Lab connects over a secure port

Code your own,
or install a ready one

Write strategies in Rust with the SDK, or install a ready one. Every download is SHA256 checked.

  • Ready strategies — tradectl install shot downloads one; the binary is SHA256 checked
  • SDK — Strategy trait with 9 order actions, full TP/SL lifecycle, a plugin interface checked when the bot loads it
  • CLI — init, build, collect, prepare, backtest, sweep, run, stop, install
  • Telegram — tradectl telegram link sends your bots' alerts to Telegram
src/lib.rs
 1  use tradectl_sdk::*;
 2  
 3  declare_strategy!("dip-buyer", DipBuyer::new);
 4  
 5  pub struct DipBuyer { dip: f64, tp: f64, sl: f64 }
 6  
 7  impl DipBuyer {
 8    pub fn new(p: &Params) -> Self {
 9      Self {
10        dip: p.get("dip", 0.5) / 100.0,
11        tp: p.get("tp", 0.3) / 100.0,
12        sl: p.get("sl", 0.5) / 100.0,
13      }
14    }
15  }
16  
17  impl Strategy for DipBuyer {
18    // EMA of 20 one-minute bars, fed by the engine
19    fn indicators(&self) -> Vec<IndicatorRequest> {
20      vec![IndicatorRequest::new(IndicatorKind::Ema, 20, 60)]
21    }
22  
23    fn on_ticker(
24      &mut self,
25      t: &TickerEvent,
26      ctx: &StrategyContext,
27    ) -> Action {
28      let Some(ema) = ctx.indicator(0) else {
29        return Action::Hold;
30      };
31      let busy = !ctx.positions.is_empty()
32        || !ctx.entry_orders.is_empty();
33      let dip = t.bid_price < ema * (1.0 - self.dip);
34      if busy || !ctx.can_enter || !dip {
35        return Action::Hold;
36      }
37      Action::PlaceEntry {
38        side: Side::Long,
39        price: Some(t.bid_price),
40        size: 0.01,
41        kind: OrderKind::Limit,
42        exits: vec![],
43        entry_id: None,
44      }
45    }
46  
47    fn on_fill(
48      &mut self,
49      f: &FillEvent,
50      _: &StrategyContext,
51    ) -> FillResponse {
52      let mut actions = vec![];
53      if f.is_entry {
54        let exit = |id: &str, price, kind| ExitOrder {
55          id: id.into(),
56          price,
57          size: f.quantity,
58          kind,
59          delay_ms: 0,
60        };
61        actions.push(Action::SetExits { exits: vec![
62          exit("tp", f.price * (1.0 + self.tp), ExitType::Limit),
63          exit("sl", f.price * (1.0 - self.sl), ExitType::Stop),
64        ]});
65      }
66      FillResponse { actions, notify: true }
67    }
68  
69    fn name(&self) -> &str { "dip-buyer" }
70  }|