Creating Custom Modules
Modules are the most powerful way to extend the functionality of Naxbot. Currently, they can be used to hook up Naxbot
to more exchanges (beyond what ccxt offers), but in the future you will be able to use them to inject completely
custom functionality to Naxbot.
As of May 2025, Naxbot is the only self-hosted trading bot to offer this functionality out of the box. Naxbot modules are programmed using TypeScript (but you can also use plain JavaScript).
By Example
Here at Naxbot, we believe in “eating our own dogfood” so to speak, so Naxbot’s ccxt integration is actually developed
using Naxbot’s module system, meaning you can use it as a starting point for writing your very own modules!
Have a look at the current iteration of the ccxt module below:
...That’s all we need to embed all of ccxt’s exchanges into Naxbot (well, all compatible exchanges anyway). Let’s break
it down!
First off, for every directory within the modules directory, Naxbot will look for a file named index.ts, which it
will then (attempt to) import as a new module. Note that it has to be named index.ts and not index.js.
Naxbot modules are written using TypeScript, and we supply all of Naxbot’s relevant types in a naxbot-types.ts file at
the root of the module directory, which you may import in order to make use of stricter type checking. This doesn’t mean
you have to write TypeScript however, as TypeScript is a superset of JavaScript, you can just write plain old JS and
not bother with any type checking if you so choose. At the end of the day, TypeScript will be transpiled into JavaScript
anyway.
Naxbot does not perform any type checking when importing modules, the ability to write TypeScript exists only for your convenience during development.
Within your index.ts, you may proceed to write TypeScript as you are used to. You can import other TS/JS files using
conventional import statements, and async/await syntax is also fully supported. Naxbot makes use of
deno under the hood to execute your code.
You may also use console.log in order to print text to stdout, but note that these logs won’t be visible in either
the web UI or the log file created by Naxbot.
For every module, Naxbot expects it to export a function named getExchanges, which takes in an object map of all
exchange configs (as specified in Naxbot’s config.toml), and is meant to return a Promise resolving to an array of
Naxbot-compatible exchange objects. Modules are expected to perform any initialization and mapping logic necessary to
produce these exchange objects, and may use async code in order to do so.
In the above example, we are enumerating through all of ccxt’s exchanges, and for each exchange we are:
- Checking whether it supports the APIs required for Naxbot to function
- Checking whether we should use testnet for the given exchange
- Mapping the
ccxtexchange to an object that can be used by Naxbot using thebuildCcxtExchangefunction
It may be tempting to use objects instantiated from classes in order to create your exchange objects, however this
will likely not work for you, as the this object will always be undefined, since Naxbot would access the functions
on the class’ prototype directly without passing this.
That is the reason why we are using arrow functions in the above example, as they can capture and retain state and do
not require implicit passing of the this object.
An exchange object must at least contain the following properties:
exchangeName: A unique name for this exchange (string)fetchOHLCV: An async function meant for fetching candlestick / kline datagetMarkets: A sync function meant to return a list of tradeable marketsfetchOrder: An async function meant to retrieve an individual order’s datacancelOrder: An async function meant to cancel an open ordercreateOrder: An async function meant to create an order on the exchange
The functions fetchOrder, cancelOrder, and createOrder are only used for actively trading on the exchange. If
you do not plan to use Naxbot to trade on your exchange, but only use it to display data, you don’t have to implement
actual functionality for these functions. Instead, you can just simply throw an error indicating that your exchange is
not meant for active trading.
All exchange objects returned by getExchanges will then automatically be registered by Naxbot and be available in the
chart, all strategies via the security function, and for trading.
Best Practices
When developing custom modules, it is a good idea to adhere to the following practices:
- Don’t change exchange names / the way you name your exchanges once you’ve started using your module, as this will cause breakage with existing data.
- Don’t perform excessive computations within TypeScript, i.e. don’t use modules to implement custom indicators. Doing so may slow down the entire bot, as Naxbot is only running one JS runtime in the background, and JavaScript is single-threaded. Implementing custom indicators in Naxbot’s Lua is also much more performant.
Possibilities
By using Naxbot’s module system, we can hook it up to any exchange that exposes a public API, be it a crypto exchange
not supported by ccxt, a stock broker, or even something completely ridiculous, like an in-game market board of an
MMO.
Frequently Asked Questions
I thought you said TypeScript/JavaScript was slow, why are we using it for modules as opposed to Lua?
While JavaScript is slower than Naxbot’s Lua for computational tasks (e.g. running a strategy), it is totally fine to use for IO-bound operations like network requests to communicate with one or more exchanges. Thanks to its built-in support for async/await syntax, it can handle multiple network connections concurrently.
When designing the interface for programming Naxbot strategies, the main goals were: Performance, simplicity, and approachability, especially by non-programmers or users of established solutions like TradingView’s PineScript. However, Naxbot modules are designed to be used by those already experienced with programming, so it made sense to use a language whose ecosystem is more fleshed out and well-known compared to that of Lua.
Finally, the ccxt library itself is written in JavaScript, and although spins of it exist in other languages, they are
all transpiled from the original JavaScript version.
Can I use node/npm modules inside Naxbot modules?
Not as of May 2025, but support for using npm modules is under active development. We expect to ship an early prototype in 2025.