BSL is an embedded JavaScript DSL. Your strategy is a single .js file that BitValue's research
engine (Athena) runs bar-by-bar over 10+ years of market data. Edit the file, re-run the backtest — no recompile,
no rebuild. The same source can later drive live execution, so what you backtest is what you trade.
The strategy is data, not a binary. Change a rule or a parameter, re-run the backtest immediately.
Real variables, if, helper methods. Stateful logic (retest machines, counters) is just this.x — no custom-language gymnastics.
One source feeds both research and signal generation, eliminating the Pine→engine rewrite drift.
No clock, no randomness, no I/O. Same inputs ⇒ same result, every time. Reproducibility is enforced, not hoped for.
// @bsl bitvalue.io/schema/bsl/v1 strategy({ name: "eth15m", params: { er_threshold_long: 60 }, setup(p) { // runs once: build indicators this.er = ind.ER(14); this.psar = ind.CustomATRPSAR(0.01, 0.03, 14); }, onBar(c, pos, p) { // runs once per closed bar if (pos.flat && this.psar.trendDir === 1 && this.er.value >= p.er_threshold_long) { enterLong("TREND_LONG", { tp: [[.05,.30],[.10,.15]], sl: .03 }); } if (pos.long && this.psar.flipped()) close("PSAR_EXIT"); plot("Custom PSAR", this.psar.value); }, });
Build indicators in setup(); read them and emit at most one position action per bar in
onBar(). Take-profit ladders and stop-losses are declared inline; the engine compiles them into
protective orders. Full host API →
.js
→
Athena backtest
→
Golden-compare vs TradingView
→
Same source → live signals
Each strategy ships with a manifest — its identity, market, parameters, data needs, signal contract, risk constraints and admission state — the single source of truth shared by backtest and live so the two never drift.
bitvalue.io/schema/bsl/v1 (human +
machine-readable descriptor); the manifest schema at
bitvalue.io/schema/strategy-manifest/v1
(human + JSON Schema). The
// @bsl … header in every strategy dereferences to its definition.