you can use Python to write directly to the database.
function onexit(){
_G('profit', profit)
}
function main(){
_G("num", 1); // Set a global variable num, with a value of 1 second
_G("num", "ok"); // Change a global variable num, whose value is the string "ok"
_G("num", null); // Delete the global variable num
_G("num"); // Return the value of the global variable num; if it does not exist, return null
var profit = 0
if(_G('profit')){
profit = _G('profit')
}
}
When placing an order, the precisions of price and volume normally need to be controlled; FMZ has builted in the _N function to determine the decimal places to be saved; for example, the result of _N(4.253,2)
is 4.25.
Calling the plaform API cannot guarantee the access is successful every time, and _C is an automatic retry function. It will always call the specified functions until it returns successfully (the function will retry if it returns null or false); for example, _C(exchange.GetTicker)
, with the default retry interval of 3 seconds, and you can call _CDelay function to control the retry interval, such as _CDelay(1000), which means to change the _C function retry interval to 1 second. It is recommended to use _C to operate fault tolerance in GetTicker()
, exchange.GetDepth
, GetTrade
, GetRecords
, GetAccount
, GetOrders
and GetOrder
to prevent the program interruption caused by the access failure.
CancelOrder
cannot use the _C function, because there are various reasons for the failure to cancel an order. If an order has been executed, then canceling the order will return a failure, and using the _C function will result in retrying all the time.
The _C function can also pass in parameters and is also used in custom functions.
function main(){
var ticker = _C(exchange.GetTicker)
var depth = _C(exchange.GetDepth)
var records = _C(exchange.GetRecords, PERIOD_D1) // Pass in the parameters
}
Calling _D()
directly will return the current time string, such as: 2019-08-15 03:46:14
. If it is called during the backtest, the backtest time will be returned. You can use the _D function to judge the time, such as: _D().slice(11) > '09:00:00':
.
_D(timestamp, fmt)
, will convert the ms timestamp to a time string, such as _D(1565855310002)
. The fmt parameter is the time format, and the default is yyyy-MM-dd hh:mm:ss
.
For some commonly used indicator functions, such as MA\MACD\KDJ\BOLL and other common indicators, which have been directly built in by FMZ platform, and the specific supported indicators can be found in the API document.
Before using the indicator functions, it is best to judge the length of K-line. When the previous K-line length cannot meet the required period for calculation, the result is null
. For example, if the input K-line length is 100 and the period for calculating MA is 10, then the first 9 values are all null, and the calculation after the formar 9 values will be done normally.
JavaScript also supports the complete talib, as a third-party library, with invocation method such as talib.CCI(records)
. Please refer to http://ta-lib.org/function.html. For Python, you can install the talib library by yourself. Due to the need for compilation, you cannot simply use pip to install. You can search for the installation method by yourself.
Indicator functions can not only pass the K-line data, but also pass any array
function main(){
var records = exchange.GetRecords(PERIOD_M30)
if (records && records.length > 9) {
var ma = TA.MA(records, 14)
Log(ma)
}
}
Here we introdue some commonly used JavaScript functions in the bots.
Date.now()
returns the current timestamp;parseFloat()
transfers strings into numbers, such as parseFloat("123.21")
;parseInt()
transfers strings into integers;num.toString()
transfers numbers into strings, with number variable num;JSON.parse()
formats Json strings, such as JSON.parse(exchange.GetRawJSON())
;Math.max()
, Math.abs()
and so on; reference: https://www.w3school.com.cn/jsref/jsref_obj_math.asp ;There are many situations that need to be considered when writing a bot strategy function. For example, a simple function such as buying 5 coins, we need to consider: Is the current balance enough? How much is the order price? What is the precision? Do you need to split orders to avoid impacting the market? How to deal with unfinished orders? And some details like that. In different strategies, these functions are the same, so you can make them into a template. Following the official templates, users can also write their own template strategies. Here we will introduce several very commonly used template class libraries officially released by FMZ, so that users can quickly write their own strategies.
The JavaScript cryptocurrency trading library and commodity futures trading library are built in by default and do not need to be copied. Other template libraries can be found at the strategy “Square” (https://www.fmz.com/square/20/1). Copy and save the template library, and check the library to be used when creating your own strategy.
JavaScript template functions all start with $
, while Python ones all start with ext
.
Source Code Address: https://www.fmz.com/strategy/10989, which has already been built-in, so no need to copy. Specific funtion implementation can directly refer to the source code.
Get Account:
$.GetAccount(e)
Log($.GetAccount()); // Obtain the account information, with fault tolerance function
Log($.GetAcccount(exchanges[1]));
Order Placing & Canceling:
$.Buy/Sell(e, amount)
$.Buy(0.3); // The main platform buys 0.3 coin
$.Sell(0.2); // The main platform sells 0.2 coin
$.Sell(exchanges[1], 0.1); // The secondary platform sells 0.1 coin
$.CancelPendingOrders(e, orderType)
$.CancelPendingOrders(); // Cancel all entrusted orders of the main platform
$.CancelPendingOrders(ORDER_TYPE_BUY); // Cancel all buy orders of the main platform
$.CancelPendingOrders(exchanges[1]); // Cancel all orders of the secondary platform
$.CancelPendingOrders(exchanges[1], ORDER_TYPE_SELL); // Cancel all sell orders of the secondary platforom
Judge the Cross:
$.Cross(periodA, periodB) / $.Cross(arr1, arr2);
var n = $.Cross(15, 30);
var m = $.Cross([1,2,3,2.8,3.5], [3,1.9,2,5,0.6])
If n = 0, it means that the current prices of exactly 15-period EMA and 30-period EMA are equal.
If n > 0, such as 5, it means that the 15-period EMA up-crosses the 30-period EMA by 5 periods (Bar)
If n < 0, such as -12, it means that the 15-period EMA down-crosses the 30-period EMA by 12 periods (Bar)
If it is not an array passed to the Cross, the function automatically obtains the K-line for moving average calculation.
If an array is passed to Cross, compare directly.
$.withdraw(e, currency, address, amount, fee, password) function:
$.withdraw(exchange, "btc", "0x.........", 1.0, 0.0001, "***")
For the use of the commodity futures trading library is very stable, it is recommended. Source code address: https://www.fmz.com/strategy/12961, which has already been built-in, so no need to copy. Specific funtion implementation can directly refer to the source code.
CTA Library
function main() {
$.CTA("rb000,M000", function(r, mp) {
if (r.length < 20) {
return
}
var emaSlow = TA.EMA(r, 20)
var emaFast = TA.EMA(r, 5)
var cross = $.Cross(emaFast, emaSlow);
if (mp <= 0 && cross > 2) {
Log("Golden cross period", cross, "the moment position", mp);
return 1
} else if (mp >= 0 && cross < -2) {
Log("Death cross period", cross, "the moment position", mp);
return -1
}
});
}
Invocation Example of library
function main() {
var p = $.NewPositionManager();
p.OpenShort("MA609", 1);
p.OpenShort("MA701", 1);
Log(p.GetPosition("MA609", PD_SHORT));
Log(p.GetAccount());
Log(p.Account());
Sleep(60000 * 10);
p.CoverAll("MA609");
LogProfit(p.Profit());
Log($.IsTrading("MA609"));
// Multiple varieties use the trading queue to complete the non-blocking trading task
var q = $.NewTaskQueue();
q.pushTask(exchange, "MA701", "buy", 3, function(task, ret) {
Log(task.desc, ret)
})
while (true) {
// Call "poll" to execute the unfinished tasks in the spare time
q.poll()
Sleep(1000)
}
}
For the raw functions for drawing are very complicated, which will be introduced in the next tutorial, we recommend beginners to use the drawing library, to draw very simple line charts and k-line charts, etc. The simple drawing library has been built in FMZ, which can be seen on the strategy editing page; if the library is not built in yet, users need to copy and save, to check and use the library in the strategy.
Copy address of Javascript version drawing library: https://www.fmz.com/strategy/27293 Copy address of Python version drawing library: https://www.fmz.com/strategy/39066
Specific example:
function main() {
while (true) {
var ticker = exchange.GetTicker()
if (ticker) {
$.PlotLine('Last', ticker.Last) // You can draw two lines at the samw time, "Last" is the name of the line
$.PlotLine('Buy', ticker.Buy)
}
Sleep(6000)
}
}
Under the “Edit Strategy”, there are strategy parameter settings, which are equal to the global variables of the strategy, and can be accessed at any location in the code. The strategy parameters can be modified on the bot page, and they will be valid after restart. Therefore, some variables can be set to the parameters, and the parameters can be modified without modifying the strategy.
It is very easy to undertand string type and number type. which are very commonly used types. The combo box will display the options in the box on the parameter interface. For example, you can set the SYMBOL paramater as BTC|USDT|ETH
in the combo box; if you choose USDT in the box on the page, the SYMBOL value in the strategy is USDT index 1. Check options refers to an optional checkbox; check means true, while no check means false.
There are more parameters for settings; referene:https://www.fmz.com/api.
When the quantization of a strategy is finished, you can test it by the history data, to check out the profit situation of the strategy in the history date. Of course, the backtest result is only for reference. FMZ Quant platform supports the backtests of cryptocurrency spot and futures, BitMEX perpetual contract, commodity futures, in which only mainstream cryptocurrencies are supported. The Javascript backtest is run on the browser; the Python backtest is on the docker, and our platform provides public dockers for users. The backtest of Mylanguage has more parameters for settings, and more details can be referred in the document of Mylanguage.
Onbar backtest mechanism is based on K-line, that is, each K-line will generate one point in time for backtest. On the point in time, you can obtain the information including the open, close, highest and lowest prices and trading volume of the current K-line, as well as the history K-line information before the point. The shortcoming of this kind of mechanism is very obvious: only one purchase can be generated on one K-line; usually the referred price is the close price of thr K-line. also, one K-line can only obtain four prices, namely the close, open, highest and lowest prices; the information, icluding how the prices change in one K-line and whether the highest price or the lowest price changes first, cannot be obtained. Take the one-hour K-line as an example. The market quote information is surely obtained every several seconds in the bot, and trading commands will be conducted in the bot not after the K-line is finished. The advantage of onbar backtest mechanism is easy to understand, and fast to backtest.
The backtest on FMZ contains two kinds, namely the simulation level backtest and the real market level backtest. The simulation level backtest can generate the simulated tick according to the underlayer K-line periods, and each underlayer K-line period will generate 14 backtest time points. However, the real market level backtest will actually collect tick, every several seconds, and now it supports real depth (inluding 20 levels), and real execution trade by tarde. The date volume is pretty huge, and the backtest speed is very slow, so the backtest cannot be run in a long time. FMZ backtest mechanism can realize multiple trades of the startegy on one K-line, to prevent the situation that the trading can only be executed by the close price, and also increasingly targeting at and taking care of the backtest speed. For more detailed instructions: https://www.fmz.com/bbs-topic/9126.
The framework of backtest and bot are the same, both an infinite loop. Because the backtest is to skip to different backtest points, the backtest can be run without using “Sleep”, and it will automatically skip to the next time point when one loop is over. However, Python, due to the program mechanism, needs a constraint of Sleep(10)
, to avoid being stuck.
The backtest engine will match the order price placed by the user and the market price at the backtest time point. If the buy price is higher than sell one, the sell one will be executed. If the trading cannot be executed, a pending order will be generated. Slippage needs to be added to ensure the trading. If the position cannot be opened or closed during the backtest, check whether the position is frozen due to unfinished orders.
GetRecords()
function; you can also specify a period parameter in the code;As we mentioned earlier, Using an API interface in the bot may fail to access and return null
; if you still use the data of it, an error will be reported and the bot will stop. Therefore, strategies need to do well in fault tolerance.
Common Causes:
API access network error; the timeout of accessing the interface returns nunll, and an error will be reported.
Platfrom limitation error, such as ip limitation, order precision, access frequency, parameter error, asset deficiency, market trading failure, the canceling of executed orders, etc.; the details can be queried in the API document according to the wrong codes.
Platform return data error; it happens sometimes, such as returning null depth, delayed account information and delayed order status, etc.
Program logic error.
Before you use the returned data of API, you should judge whether the data is null, and the common methods are introduced as follows:
//1.judge the data is null and handle
var ticker = exchange.GetTicker();
while(ticker == null){
Log('ticker obtain error');
ticker = exchange.GetTicker();
}
Log(ticker.Last);
// 2. judge the data is not null, and use
var ticker = exchange.GetTicker();
if(!ticker){
Log(ticker.Last);
}
// 3.retry _C() function
var ticker = _C(exchange.GetTicker);
Log(ticker.Last);
// 4.try cache fault tolerance
try{
var ticker = exchange.GetTicker();
Log(ticker.Last);
}
catch(err){
Log('ticker obtain error');
}
If you want to obtain the information of erors, you can use GetLastError()
, and the strings of the last time error information will be returned, and the errors can be processed by differences.
Common error summary in the top posts of the forums: https://www.fmz.com/bbs-topic/9158. Here we introduce it in brief; you can use ctrl+F to search, when you have problems.
How to deploy the docker?
There is a detailed introdution about it in the section of adding a docker.
Can I ask someone to ghostwrite strategies for me?
on https://www.fmz.com/markets , there are some people who provide services of writing strategies for others, or you can ask in the chatting groups; notice that those kind of services shall be contacted by yourself, and you should be aware that the risk shall also be borne by yourself.
All interfaces prompt timeout when acessed
it refers to the timeout of the accessed platform interface; if the timeout happens occasionally, it is not a problem; if the timeout is prompted all the time, that means all networks cannot be accessed and an overseas server is needed.
ERR_INVALID_POSITION
If the backtest reports an error, it is generally a writing error; when you try to place an order to close a position, when there is no position or the position volume is not enough, an error will be reported.
Symbol not set
There is no contract set in the code, durig the backtests of futures platforms. Refer to exchange.SetContractType function.
BITMEX 429error,{“error”:{“message”:“Rate limit exceeded retry in 1 seconds ……”}}
The access frequency of the platform interface is too high.
{“status”:6004,“msg”:“timestamp is out of range”}
The timestamp of the server exceeds the time range of updating the server, and the exceeded time cannot be too long.
GetOrder(455284455): Error: invalid order id or order cancelled.
If the order of a platform is cancelled, the platform will not maintain the order information anymore, so the information cannot be obtained.
GetOrders: 400: {“code”:-1121,“msg”:“Invalid symbol.”}
Invalid trading pair; check out if the tradig pair setting is wrong.
Secret key decrypt failed
The APIKEY parsing fails. If the FMZ password has been modified after the APIKEY is configured, try to add a platform page on FMZ and reconfigure the platform APIKEY.
Signature not valid: invalid submission time or incorrect time format
suggest you use Linux server, or install time synchronization software on these Windows systems where this problem occurs.
Why the docker still cannot access the platform API when a global proxy is set?
The global proxy does not have a proxy docker network port. Due to the delay problem, it is best to deploy the docker of an overseas server.
How to save a strategy locally, not to upload it to FMZ?
Using Python, and you can import local files, save the strategy normally written by FMZ API as a file and put it in the execution path on your own server, and you can directly read and execute it.
#!python2.7
def run(runfile):
with open(runfile,"r") as f:
exec(f.read())
def main():
run('my.py')
How to the testnet of a platform or how to change API base address?
Use exchange.SetBase() to directly switch to the corresponding API base address. For example:
exchange.SetBase("https://www.okex.me")