Local Backtesting Engine
The platform publishes local backtest engines for JavaScript and Python. They use the same engine core and the same history data (downloaded from the platform's data server) as cloud backtests, and backtest JavaScript and Python strategies quickly on your own computer. Source code:
Python
Install (requires Python 3 and pip):
bash
pip install https://github.com/fmzquant/backtest_python/archive/master.zip
pip install pandas matplotlib # only needed for Join(True) and Show()
On first use the package downloads the engine file for your system from the data server; afterwards only history data is downloaded. A strategy file is an ordinary FMZ strategy plus the backtest configuration comment at the top (format: see Backtest Configuration and Saving; the local engines read only some of its keys, see "Differences from cloud backtests" below) and a few lines that drive the engine:
python
'''backtest
start: 2026-09-01 00:00:00
end: 2026-09-15 00:00:00
period: 1h
basePeriod: 15m
exchanges: [{"eid":"Binance","currency":"BTC_USDT","balance":10000,"stocks":0}]
'''
import json
from fmz import *
# initialize the engine from the configuration above; exchange, Log, TA etc. become globals
task = VCtx(__doc__)
# The strategy under test, copied from the platform as is
def main():
Log(exchange.GetAccount())
while True:
r = exchange.GetRecords()
if r:
LogStatus(_D(), r[-1]["Close"])
Sleep(60 * 60 * 1000)
try:
main()
except EOFError: # The engine raises EOFError when the virtual clock reaches the end time
pass
result = json.loads(task.Join(False)) # Raw backtest result (JSON)
print(result["LogsCount"], result["Elapsed"] / 1e6)
# task.Show() # Or show the profit chart (requires matplotlib)
Run it with python strategy.py. task.Join(False) returns the raw result as JSON, task.Join(True) returns a pandas DataFrame of the first exchange account's profit and loss (PnL) and utilization at each snapshot, and task.Show() plots equity, profit and loss and utilization from the account snapshots; neither depends on LogProfit().
JavaScript
bash
npm install git+https://github.com/fmzquant/backtest_javascript.git
javascript
var fmz = require("fmz")
var task = fmz.VCtx({
start: "2026-09-01 00:00:00", end: "2026-09-15 00:00:00", period: "1h", basePeriod: "15m",
exchanges: [{eid: "Binance", currency: "BTC_USDT", balance: 10000, stocks: 0}]
})
// From here on exchange, Log, TA etc. are globals; paste the strategy code and call main()
function main() {
Log(exchange.GetAccount())
while (true) {
var r = exchange.GetRecords()
if (r) {
LogStatus(_D(), r[r.length - 1].Close)
}
Sleep(60 * 60 * 1000)
}
}
try {
main()
} catch (e) {
// The engine throws "EOF" when the virtual clock reaches the end time
}
var result = JSON.parse(task.Join()) // Same result as Join(False) of the Python engine
console.log(result.LogsCount)
Differences from cloud backtests
- Only JavaScript and Python strategies are supported and templates are not loaded automatically: paste the code of referenced templates into the file. PINE and MyLanguage strategies depend on trading libraries and therefore cannot be backtested locally.
- Strategy parameters are not injected; define them as global variables in the code.
startandendin the comment are parsed in the machine's time zone; network delay is fixed at 200 ms; slippage and real-tick mode are not supported.- Only
start,end,period,basePeriodandexchanges(with itseid,currency,balance,stocks,fee,feeMin) are read from the comment;mode,args,depthDeep,tradesMode,feederand the like are ignored. WithoutbasePeriodit is derived fromperiod(1d→1h, 1h→30m, 30m→15m, 15m→5m, 5m→1m); withoutstocksthe default is 3; withoutfeethe engine's built-in fee table is used. It is best to write them all out.
Backtesting with an AI assistant
An AI assistant can run backtests for you: it starts a cloud backtest with the MCP tool run_backtest and reads profit, drawdown, error logs and other results with get_backtest, see AI Integration. It can also install the local engine on your machine for a fast edit-and-run loop, then confirm once with a cloud backtest.