Loading ...

[TOC]

Basic Instructions

Getting Started

What can the FMZ Quant platform do?

FMZ Quant platform (formerly known as BotVS) is the most professional quantitative trading community in China. Here you can learn, write, share, buy and sell quantitative trading strategies, backtest them online and use simulated trading market to simulate transactions. also you can run, open, and operate the real market from our platform’s excellent API connection. We mainly focus on almost all commonly used cryptocurrency exchanges, we also supports traditional Chinese commodity futures market.

A complete series of tutorials

Graphic Tutorial:

If you encounter any problem, you can post a question at the forum at any time, or send a work order, or in the Telegram group, QQ group and WeChat group @administrator, generally will be answered quickly.

Support:

  • Telegram Group https://t.me/fmzquant

  • QQ Group

    • 863946592
    • 456221748
    • 469046711
    • 608262365
    • 309368835
  • WeChat Group img

What programming languages ​​are available to implement my strategy?

FMZ Quant supports JavaScriptPythonC++M LanguageBlockly Programming to write trading strategies. JavaScript Quick Start Python Quick Start M Language Quick Start.You only need to master one of these options. In addition to supporting writing code to write strategies, you can also use visualization modules to create strategies. The visualization module splicing construction strategy adopts a more intuitive way to design strategies without coding, which is very suitable for cultivating strategy design interest and getting started with quantitative trading.

Blockly Programming Tutorial:

What is a Docker?

Docker can be understood as the executor of your trading strategy, responsible for complex data requests, data reception, network links, log postbacks and more. The docker runs on your server, even if the FMZ website has a network failure, it will not affect the operation of your docker. The docker can be run on Linux, Windows, Mac OS, Android, Raspberry Pi and other system. Docker Page,Linux docker installation and update steps. The robots and logs managed by the docker are stored in the directory./logs/storage, The file is a Sqlite database file of db3, which can be directly edited by the Sqlite management software. The file name is the robot ID.

Supported Exchanges

Blockchain assets: 50 mainstream blockchain assets (cryptocurrency) exchanges are now supported. Commodity futures: support CTP agreement, Esunny agreement and see-through supervision.

Types
Commodity Futures Futures_CTP, Supports all commodity futures in China
Esunny Protocol Futures_Esunny, Support global futures varieties
cryptocurrency Spot AEX HBTC Poloniex Bibox BigONE
Binance BitZ BitFlyer BitMax BitGoGo
Bitfinex Bithumb Zaif Bitstamp Bittrex
ZBG Hydax CoinEx FUBT STEX
Coincheck Coinone Coinw DigiFinex DragonEx
EXX Hoo GateIO HitBTC Quoine
Huobi KEX Korbit Kraken KuCoin
LiveCoin OKCoin_EN OKEX OKEX_V3 BW
MXC ZB BitMart Bitget FTX
cryptocurrency futures (delivery contracts) Futures_BitMEX Futures_Deribit Futures_HuobiDM Futures_OKEX Futures_OKEX_V3
Futures_Kraken Futures_Binance Futures_FTX
cryptocurrency futures (perpetual contract) Futures_BitMEX Futures_Deribit Futures_GateIO Futures_OKEX_V3 Futures_BFX
Futures_Bibox Futures_BitZ Futures_Binance Futures_Bitfinex Futures_JEX
Futures_Bybit Futures_Kraken Futures_Bitget Futures_HuobiDM Futures_FTX
cryptocurrency spot simulation exchange WexApp
cryptocurrency spot leveraged exchange OKEX_V3 Huobi Bibox ZB Binance
cryptocurrency Options Exchange Futures_Deribit Futures_JEX Futures_OKEX_V3 Futures_FTX

Special Exchange Notes:

  • BitMart Since the authentication method is the OAuth 2.0 method, if two robots share the same API KEY, the two robots may continuously apply for tokens with each other (because data cannot be shared between robots), so for this exchange, it is recommended that each robot be configured with a separate API key.

  • Futures_Binance Support Binance Futures two-way holding position mode, you can use exchange.IO to switch:

    function main() {
        var ret = exchange.IO("api", "POST", "/fapi/v1/positionSide/dual", "dualSidePosition=true")
        // ret : {"code":200,"msg":"success"}
        Log(ret)
    }
    
    def main():
        ret = exchange.IO("api", "POST", "/fapi/v1/positionSide/dual", "dualSidePosition=false")
        Log(ret)
    
    void main() {
        auto ret = exchange.IO("api", "POST", "/fapi/v1/positionSide/dual", "dualSidePosition=true");
        Log(ret);
    }
    

Strategy security

When develop trading strategies on FMZ platform, the strategy contents are only visible to the FMZ account holders. Users also can deploying the strategy code completely localized. For example, a strategy logic can be packaged into a Python package, which is loaded in the strategy code, so that the strategy content localization can be realized.

Security of Python code:

Because Python is an open source and easily decompilable language, if the strategy is not for own use but for rent, if you are worried about the strategy leakage, you can let the strategy run on the docker deployed by you and be managed in the form of sub-account or full hosting rent.

Python writing strategy code encryption:

By default, Python strategy code authors do not encrypt when they use it, but encrypt it when rented out to others. Edit the following code at the beginning of the Python strategy, you can specify whether to encrypt the strategy code when you use or rent out the strategy.

The Python versions that support strategy code encryption are various versions from Python 2.7 to Python 3.7.

  • The strategy author runs it himself and uses the registration code for others to encrypt the strategy code:

#!python is to specify the version of the Python interpreter, then use comma , to enter the encryption command encrypt. If you don’t specify the Python version, just add #!,encrypt.

#!python,encrypt

Or

#!,encrypt
  • The strategy author does not encrypt the strategy code if he runs it himself or uses it with others through the registration code:
#!python,unencrypt

Or

#,unencrypt

To determine whether the encryption of the Python strategy code is effective, use os.getenv('__FMZ_ENV__'), and return the string "encrypt", indicating that it has taken effect. Only the real market is valid, and the backtest will not encrypt the Python strategy code.

#!,encrypt
def main():
    ret = os.getenv('__FMZ_ENV__')
    # Print variable ret is the string encrypt or ret == "encrypt" is true, which means that the encryption takes effect
    Log(ret, ret == "encrypt")

Key security

The sensitive information such as account information and encrypted strings in the strategy parameters configured on the FMZ platform are encrypted on the web browser side. The information stored on the FMZ platform are encrypted information (non-clear text data), Only the user’s private device can be decrypted, which greatly improves the security of sensitive data.

Backtest System

What is a backtest system and what is it for?

After you have completed the quantitative work of a trading strategy, how can you know the basic situation of your strategy, such as the logic of the strategy, and the direction of the strategy’s income? Of course, we cannot directly use real money to run strategies on the real trading market. We can use historical data to test your strategy and see how profitable your strategy is in historical data, whether it is losing money or making money.

Is the data of the backtest system accurate and the results credible?

FMZ divides the backtest system into real level and simulation level. The real level is backtested completely according to the complete historical data. The simulation level generates the k-line at regular intervals for backtesting. They both based on the real historical data, but the real level data is more accurate and the results are more credible. FMZ Backtest Mechanism Description. Backtest is just the performance of the strategy under historical data. Historical data does not fully represent the future market. The historical market may repeat itself or it may fly out of a black swan. So treat the backtest results rationally and objectively.

Factors need to pay attention when backtest different programming language written trading strategies:

JavaScript and C++ trading strategies. The backtesting is performed on the web browser end. The real market robot or simulation market robot (ie, the simulation market of BotVS) runs without installing any other software, libraries or modules. Python backtest is performed on the docker, and also can be backtested on the public server created by FMZ Quant. The real market operation and backtest both rely on Python installed on the system where the docker is located. If you need to use some libraries, you need to install them yourself (only common libraries are supported on public servers). When using a trading strategy written in Python, if the docker’s system environment has both Python2 and Python3 installed, you can set the version of Python by adding the code in the first line of the strategy code. Such as #!python3, #!python2, this will automatically find the right interpreter. You can also specify an absolute path, for example: #!/usr/bin/python3.

Backtest Data

There are two types of FMZ platform backtest: simulation level backtest and real market level backtest. The simulation level backtest generates simulated ticks based on the underlying K-line period. Each K-line period will generate 14 backtesting time points, while the real market level is the actual collected “ticks”, which will occur once every few seconds. The amount of data It is very large and the backtesting speed is slow, so it cannot be backtested for a very long period of time. FMZ’s backtest mechanism allows the trading strategy to trade multiple times on a single K-line, avoiding the situation where the transaction can only be executed at the closing price. It is more accurate while taking into account the speed of backtest. For specific instructions, please refer to Link.

Simulation Level

The simulation-level backtest is based on the underlying K-line data of the backtest system, and according to a certain algorithm, the ticker data is simulated in a frame composed of the highest, lowest, opening, and closing prices of the given underlying K-line Bar. Returned as real-time tick data when the interface is requested. For details, please refer to:FMZ Quant Simulation Level Back Test Mechanism Description.

Real Market Level

The real market level backtest is the actual ticker level data in Bar’s time series. For strategies based on ticker-level data, using real market level backtesting is closer to reality. In Real market level backtesting, ticker is real recorded data, not simulation. Support depth data, market transaction record data playback, custom depth and each individual transaction data. The capability backtest data of the real market level is up to maximum of 50MB. The backtest time range is not limited within the upper limit of the data. If you need to increase the backtest time range as much as possible, you can reduce the value of the depth gear setting and do not use each individual transaction data to increase the backtest time range. Call GetDepth,GetTrades functions to obtain playback market data. At a moment of market data on the timeline, calling GetTicker,GetTrades, GetDepth,GetRecords will not push the time multiple times when the time moves on the backtest timeline (does not trigger a jump to the next market data moment). Repeated calls to one of the above functions will push the backtest time to move on the backtest timeline (jump to the next market data moment). When use the real market level for backtesting, It is not recommended to choose a earlier time. There may be no real market level data in the premature time period.

The real market level backtest currently supports:

  • Commodity Futures
  • Binance
  • OKEX(OKEX Spot)
  • HuobiDM(Huobi Futures)

Custom data source

The system uses the GET method to request a custom URL (publicly accessible URL) to obtain an external data source for backtesting. The additional request parameters are as follows:

Parameter Meaning Explanation
Symbol Symbol Name For Example : BTC_USD_OKCoin_EN
Eid Exchange eg: OKCoin_EN
Round Price Accuracy as 3 then the price in the returned data must be multiplied by 1000 rounding
vround Quantity Accuracy as 2 then the quantity in the returned data must be multiplied by 100 rounded
Period Bar Period (Milliseconds) such as 60,000 for request minutes bar
Depth Depth Steps 1-20
Trades Whether Need To Split Data true/false
From Start Time Unix Timestamp
To End Time Unix Timestamp

Note:

Round and vround are two parameters designed to avoid loss of precision of floating-point numbers during network transmission. The numbers are transmitted using shaping.

An example of the stitched data:

http://customserver:80/data?symbol=BTC_USD_OKCoin_EN&eid=OKCoin_EN&round=3&vround=3&period=900000&from=1564315200&to=1567267200

The returned format must be the following two formats (any two formats can be returned, the system automatically recognizes):

Ordinary Bar Level Backtest

{
    "schema":["time","open","high","low","close","vol"],
    "data":[[1564315200000,9531300,9531300,9497060,9497060,787],[1564316100000,9495160,9495160,9474260,9489460,338]]
}

Tick-level backtest data (contains market depth information, an array of depth format is [Price,Volume], there can be multiple levels of depth, asks for ascending price, and bids for reverse price)

{
    "schema":["time","asks", "bids","trades","close","vol"],
    "data":[[1564315200000,[[9531300,10]], [[9531300,10]],[[1564315200000,0,9531300,10]],9497060,787]]
}

Description

Field Description
Schema specifies the attributes of the columns in the data array, which is case sensitive, only limit to time, open, high, low, close, vol, asks, bids
Data An array that stores data by schema
Detail Attributes Required for Commodity Futures

detail Field

Field Description Examples
PriceTick Price one pip jumping value 0.1
VolumeMultiple How many units in a lot 100
ExchangeID ExchangeID CZCE
LongMarginRatio Long Margin Ratio 0.2
ShortMarginRatio Short Margin Ratio 0.2
InstrumentID Contract real market code rb1906

Data Format

Field Description
asks/bids [[price,quantity],…]
trades [[time,direction(0:buy,1:sell),price,quantity],…]

Custom data source example:

Specify the data source, URL:http://xxx.xx.x.xx:9090/data Custom data server, written in golang:

package main 
import (
    "fmt"
    "net/http"
    "encoding/json"
)

func Handle (w http.ResponseWriter, r *http.Request) {
    // e.g. set on backtest DataSourse: http://xxx.xx.x.xx:9090/data
    // r.URL: /data?depth=20&detail=true&eid=Binance&from=1566820800&period=900000&round=3&symbol=BTC_USDT_Binance&to=1569686400&trades=1&vround=5
    // response
    defer func() {
        // response data
        /* e.g. data
        {
            "schema":["time","open","high","low","close","vol"],
            "data":[
                [1564315200000,9531300,9531300,9497060,9497060,787],
                [1564316100000,9495160,9495160,9474260,9489460,338]
            ]
        }
        */
        ret := map[string]interface{}{
            "schema" : []string{"time","open","high","low","close","vol"},
            "data" : []interface{}{
                []int64{1564315200000,9531300,9531300,9497060,9497060,787},
                []int64{1564316100000,9495160,9495160,9474260,9489460,338},
            },
        }
        b, _ := json.Marshal(ret)
        w.Write(b)
    }()
}

func main () {
    fmt.Println("listen http://localdocker:9090")
    http.HandleFunc("/data", Handle)
    http.ListenAndServe(":9090", nil)
}

Testing strategies, JavaScript examples:

/*backtest
start: 2019-07-28 00:00:00
end: 2019-07-29 00:00:00
period: 1m
exchanges: [{"eid":"OKEX","currency":"BTC_USDT","feeder":"http://120.24.2.20:9090/data"}]
*/

function main() {
    var ticker = exchange.GetTicker()
    var records = exchange.GetRecords()
    Log(ticker)
    Log(records)
}

Charts drawn from custom data in the backtest system: Strategies print information:

Local Backtest Engine

FMZ Quant trading platform has open sourced the JavaScript version and the Python version of local backtesting engine, and also supports setting Underlying K line cycle during backtest.

Backtest Page Shortcuts

  • Shortcuts for switching between the strategy edit page and the strategy backtest page

    Use the Ctrl +, keys to switch back to the backtest page and the strategy editing page. After holding down the Ctrl key, then press the , key.

  • Shortcuts for strategy edit saving

    Use Ctrl + s to save the edited code.

  • Shortcuts for strategy backtest

    Use Ctrl + b to start the backtest.

Code Description

Entry Function

Function name Description
main() as an entry function.
onexit() As a normal exit tail sweep function, the maximum execution time is 5 minutes, which can be left unspecified. If the timeout occurs, an interrupt error will be reported.
onerror() As an abnormal exit function, the maximum execution time is 5 minutes, which can be left unspecified. The strategy written in Python does not support this function.
init() As an initialization function, the strategy program will be called automatically when it starts running, but it may not be declared.
  • Description:
    • 1、Backtest system doesn’t support onerror().
    • 2、In the real market or wexApp simulation market, after the onerror() function is triggered, the onexit() function will not be triggered.

onexit()

Processing tail sweeping work, the maximum execution time is 5 minutes, which is realized by the user.

function main(){
    Log("Start running, stop after 5 seconds, and execute the sweep function!")
    Sleep(1000 * 5)
}

// Tail sweep function implementation
function onexit(){
    var beginTime = new Date().getTime()
    while(true){
        var nowTime = new Date().getTime()
        Log("The program stops counting down..The sweep starts and has passed:", (nowTime - beginTime) / 1000, "Seconds!")
        Sleep(1000)
    }
}
import time 
def main():
    Log("Start running, stop after 5 seconds, and execute the sweep function!")
    Sleep(1000 * 5)

def onexit():
    beginTime = time.time() * 1000
    while True:
        ts = time.time() * 1000
        Log("The program stops counting down..The sweep starts and has passed:", (ts - beginTime) / 1000, "Seconds!")
        Sleep(1000)
void main() {
    Log("Start running, stop after 5 seconds, and execute the sweep function!");
    Sleep(1000 * 5);
}

void onexit() {
    auto beginTime = Unix() * 1000;
    while(true) {
        auto ts = Unix() * 1000;
        Log("The program stops counting down..The sweep starts and has passed:", (ts - beginTime) / 1000, "Seconds!");
        Sleep(1000);
    }
}

init()

The user implements the initialization function init(), which will automatically execute the init() function at the beginning of the strategy to complete the initialization task.

function main(){
    Log("The first line of code is executed!", "#FF0000")
    Log("Exit!")
}

// Initialization Function
function init(){     
    Log("Initialization!")
}
def main():
    Log("The first line of code is executed!", "#FF0000")
    Log("Exit!")

def init():
    Log("Initialization!")
void main() {
    Log("The first line of code is executed!", "#FF0000");
    Log("Exit!");
}

void init() {
    Log("Initialization!");
}

onerror()

When an exception occurs, onerror() function execution is triggered. This function does not support Python writing strategy.

function main() {
    var arr = []
    Log(arr[6].Close)
}

function onerror() {
    Log("error")
}
# python does not support
// C++ does not support

Classic Trading Strategy Framework

In strategies written in JavaScript, Python, C++ languages, the Sleep() function needs to be called in the main loop of the strategy, it will be used to control backtesting time series backtracking speed. In the real market, it is used to control the strategy polling interval, and also control the frequency of accessing the API interface of the exchange. Because the strategy for commodity futures is event-driven (the market data is pushed by the exchange), the strategy for commodity futures can be written without the Sleep() function.

  • Example of basic framework of cryptocurrency strategies:

    function onTick(){
        // Write strategy logic here, it will be called constantly, such as printing market information.
        Log(exchange.GetTicker())
    }
    
    function main(){
        while(true){
            onTick()
            // Sleep function is mainly used to control the polling frequency of cryptocurrency strategies to prevent access to the exchange API interface too frequently
            Sleep(60000)
        }
    }
    
    def onTick():
        Log(exchange.GetTicker())
    
    def main():
        while True:
            onTick()
            Sleep(60000)
    
    void onTick() {
        Log(exchange.GetTicker());
    }
    
    void main() {
        while(true) {
            onTick();
            Sleep(60000);
        }
    }
    

    For the simplest example, if I want to place a buy order with a price of 100 and a quantity of 1 on the exchange every 1 second, I can write:

    function onTick(){
        exchange.Buy(100, 1)
    }
    
    function main(){
        while(true){
            onTick()
            // The pause period can be customized in milliseconds (1 second = 1000 milliseconds)
            Sleep(1000)
        }
    }
    
    def onTick():
        exchange.Buy(100, 1)
    
    def main():
        while True:
            onTick()
            Sleep(1000)
    
    void onTick() {
        exchange.Buy(100, 1);
    }
    
    void main() {
        while(true) {
            onTick();
            Sleep(1000);
        }
    }
    
  • Classic Commodity Futures Strategies Structure:

    function main(){
        while(true){
            // Only when the exchange.IO("status") function returns true, that is, is it true, can the market, transaction and other functions be called
            if(exchange.IO("status")){
                exchange.SetContractType("MA000")
                var ticker = exchange.GetTicker()
                Log("MA000 ticker:", ticker)
                LogStatus(_D(), "CTP is connected!")
            } else {
                LogStatus(_D(), "CTP is not connected!")
            }
        }
    }
    
    def main():
        while True:
            if exchange.IO("status"):
                exchange.SetContractType("MA000")
                ticker = exchange.GetTicker()
                Log("MA000 ticker:", ticker)
                LogStatus(_D(), "CTP is connected!")
            else:
                LogStatus(_D(), "CTP is not connected!")
    
    void main() {
        while(true) {
            if(exchange.IO("status") == 1) {
                exchange.SetContractType("MA000");
                auto ticker = exchange.GetTicker();
                Log("MA000 ticker:", ticker);
                LogStatus(_D(), "CTP is connected!");
            } else {
                LogStatus(_D(), "CTP is not connected!");
            }
        }
    }
    

Template Class Library

Template Class Library is a reusable code module in the FMZ Quant trading platform, and is a category of trading strategy code. When creating a trading strategy, if the category is set to Template Class Library, a template class library is created in the strategy library account that currently logged in the FMZ Quant trading platform. Once created, it is no longer possible to modify the category to a normal strategy.

  • Export function of template class library The exported function is an interface function of the template class library, and can be called by a strategy that references the template class library. The exported function is declared and implemented in the template class library as follows:

    /*
    -- This method is called directly with $.Test() after the strategy references the template.
    -- main function will not triggered in the strategy, it is only used as the entry point for template debugging.
    */
    $.Test = function() {
        Log('Test')
    }
    
    function main() {
        $.Test()
    }
    
    def Test():
        Log("template call")
    
    # Export Test function, the main strategy can be called by ext.Test()
    ext.Test = Test 
    
    // The strategy refers to this template and calls this method directly with ext::Test()
    void Test() {
        Log("template call");
    }
    
  • Parameters of the template class library The template class library can also set its own interface parameters. The parameters of the template class library are used in the form of global variables in the template class library code.

    Template class library setting parameters:

    Template class library code:

    $.SetParam1 = function(p1) {
        param1 = p1
    }
    
    $.GetParam1 = function() {
        Log("param1:", param1)
        return param1
    }
    
    def SetParam1(p1):
        global param1
        param1 = p1
    
    def GetParam1():
        Log("param1:", param1)
        return param1
    
    ext.SetParam1 = SetParam1
    ext.GetParam1 = GetParam1
    
    void SetParam1(float p1) {
        param1 = p1;
    }
    
    float GetParam1() {
        Log("param1:", param1);
        return param1;
    }
    

    The strategy code that quote the Template Class Library example above:

    function main () {
        Log("Call $.GetParam1:", $.GetParam1())
        Log("Call $.SetParam1:", "#FF0000")
        $.SetParam1(20)
        Log("Call $.GetParam1:", $.GetParam1())
    }
    
    def main():
        Log("Call ext.GetParam1:", ext.GetParam1())
        Log("Call ext.SetParam1:", "#FF0000")
        ext.SetParam1(20)
        Log("Call ext.GetParam1:", ext.GetParam1())
    
    void main() {
        Log("Call ext::GetParam1:", ext::GetParam1());
        Log("Call ext::SetParam1:", "#FF0000");
        ext::SetParam1(20);
        Log("Call ext::GetParam1:", ext::GetParam1());
    }
    

  • Reference the template class library

    After click the reference option, save the strategy.

Built-in Structure

Global Variables

exchange

It can be regarded as an exchange object. By default, it is the first exchange added in the strategy parameters. All data interaction with the exchange is realized through the functions in this object.

  • Backtesting adding exchange objects

  • Add exchange object on real market robot page

The added exchange object corresponds to the exchange object in the code:

function main() {
    Log("The name of the first exchange object added on the real market robot page or backtest page:", exchange.GetName(), "label:", exchange.GetLabel())
}
def main():
    Log("The name of the first exchange object added on the real market robot page or backtest page:", exchange.GetName(), "label:", exchange.GetLabel())
void main() {
    Log("The name of the first exchange object added on the real market robot page or backtest page:", exchange.GetName(), "label:", exchange.GetLabel());
}
exchanges

An array of exchange, which contains multiple exchange objects, exchanges[0] means exchange.

The added exchange objects correspond to exchanges[0], exchanges[1], exchanges[2] … in the strategy code, and so on.

function main() {
    for(var i = 0; i < exchanges.length; i++) {
        Log("Index of the exchange object added (the first one is 0 and so on):", i, "Name:", exchanges[i].GetName(), "label:", exchanges[i].GetLabel())
    }
}
def main():
    for i in range(len(exchanges)):
        Log("Index of the exchange object added (the first one is 0 and so on):", i, "Name:", exchanges[i].GetName(), "label:", exchanges[i].GetLabel())
void main() {
    for(int i = 0; i < exchanges.size(); i++) {
        Log("Index of the exchange object added (the first one is 0 and so on):", i, "Name:", exchanges[i].GetName(), "label:", exchanges[i].GetLabel());
    }
}
Order Status

Status attribute in the Order structure.

Constant Name Definition Value
ORDER_STATE_PENDING unfinished 0
ORDER_STATE_CLOSED finished 1
ORDER_STATE_CANCELED already cancelled 2
ORDER_STATE_UNKNOWN Unknown state (other states) 3

ORDER_STATE_UNKNOWN status, you can call exchange.GetRawJSON() to get the original order status information, query the exchange document, and see the detailed description.

Order Type

Type attribute in the Order structure.

Constant Name Definition Value
ORDER_TYPE_BUY Buying Order 0
ORDER_TYPE_SELL Selling Order 1
Position Type

Type attribute in the Position structure.

Constant Name Definition Description Applicable Value
PD_LONG Long positions CTP uses exchange.SetDirection(“closebuy_today”) to set the closing position direction, and cryptocurrency futures use exchange.SetDirection(“closebuy”) to set the closing position direction Commodity Futures, cryptocurrency Futures 0
PD_SHORT Short positions CTP uses exchange.SetDirection(“closesell_today”) to set the closing position direction, and cryptocurrency futures use exchange.SetDirection(“closesell”) to set the closing position direction Commodity Futures, cryptocurrency Futures 1
PD_LONG_YD Long positions yesterday CTP uses exchange.SetDirection(“closebuy”) to set the closing position direction Commodity Futures 2
PD_SHORT_YD Short positions yesterday CTP uses exchange.SetDirection(“closesell”) to set the closing position direction Commodity Futures 3
Futures opening and closing position direction

Offset attribute in the Order structure.

Constant Name Definition Value
ORDER_OFFSET_OPEN Opened Position Orders 0
ORDER_OFFSET_CLOSE Closed Position Orders 1
Strategy Parameters

In the trading strategy code, the strategy parameters set on the strategy interface are reflected in the form of global variables. JavaScript language can directly access the parameter values set or modified on the strategy interface, Python modify the global variables in the strategy need to use the global keyword.

Parameter Types:

Variable Description Remarks Type Default Value Description
number Number type Remarks Number (number) 1 C ++ strategy is float type
string String Remarks String(string) Hello FMZ The default value does not need to be quoted. The input is treated as a string
combox Drop-down box Remarks Drop-down box(selected) 1|2|3 The combox variable itself is a numerical value, which represents the index of the column selected by the drop-down control. Value is 0, and so on
bool Check Options Remarks Boolean(true/false) true If checked, the variable bool is true, if not checked, the variable bool is false
secretString Encrypted String Remarks Encrypted String(string) passWord Use the same as a string, the encrypted string will be sent encrypted and will not be transmitted in plain text
  • Interface parameters are set in the strategy parameter area below the code editing area of the strategy editing page.
  • Interface parameters exist as global variables in the strategy code, that is, interface parameters can be modified in the code.
  • The variable name of the interface parameter in the strategy code(see above picture): number,string, combox,bool, secretString.
  • Description option: The name of the interface parameter on the strategy interface.
  • Remark options: Detailed description of the interface parameters. This description will be displayed when the mouse is hovering over the interface parameters.
  • Type option: the type of this interface parameter.
  • Default value option: The default value of this interface parameter.

Parameter dependent settings: One parameter can be set to allow another parameter to be displayed and hidden based on the selection of the parameter. For example, we set the parameter numberA, which is a numeric type. We let numberA show and hide based on a parameter: isShowA (boolean type) true or false. You need to set the numberA variable on the interface parameters to: numberA@isShowA.

In this way, if the isShowA parameter is not checked, the numberA parameter is hidden.

Strategy interface parameters, interactive controls, and parameter grouping functions on templates: Just add (?First group) at the beginning of the description of the parameter that starts the grouping. As shown in the figure:

When the strategy is in using, the parameters are displayed in groups:

Parameter default values saving: The strategy parameters are shown in the figure. During the backtest, if you want to save the default values of the strategy parameters, you can click the Save backtest settings button after the strategy parameters are modified.

You can save the strategy parameters setting in code form:

/*backtest
start: 2020-02-29 00:00:00
end: 2020-03-29 00:00:00
period: 1d
args: [["number",10],["string","Hello FMZ"],["combox",1],["bool",false]]
*/
'''backtest
start: 2020-02-29 00:00:00
end: 2020-03-29 00:00:00
period: 1d
args: [["number",10],["string","Hello FMZ"],["combox",1],["bool",false]]
'''
/*backtest
start: 2020-02-29 00:00:00
end: 2020-03-29 00:00:00
period: 1d
args: [["number",10],["string","Hello FMZ"],["combox",1],["bool",false]]
*/

Data Structure

Some functions will be accompanied by the original JSON information requested during the call. The original JSON data is stored in the Info attribute of the returned object. Since the backtest is not an interface to access an exchange, it is returned during the backtest that has no Info attribute in the data. The following is a description of the main attributes of each data structure.

Trade

Get all transaction history (not itself), returned by exchange.GetTrades() function.

{
    Time    : 1567736576000,    // Time (Unix timestamp milliseconds)
    Price   : 1000,             // Price          
    Amount  : 1,                // Quantity
    Type    : 0                 // Order type, refer to the order type in the constant, 0 is ORDER_TYPE_BUY, ORDER_TYPE_BUY is 0
}
Ticker

Market quotes are returned by the exchange.GetTicker() function.

{
    Info    : {...},             // After requesting the exchange interface, the original data of the exchange interface response, this attribute is not available during the backtest
    High    : 1000,              // highest price
    Low     : 500,               // lowest price
    Sell    : 900,               // Selling price 1
    Buy     : 899,               // Buying price 1
    Last    : 900,               // Last traded price
    Volume  : 10000000,          // Recent trading volume
    Time    : 1567736576000      // Millisecond-level timestamp
}
Record

The standard OHLC structure is used to draw K-line and indicator analysis. The exchange.GetRecords() function returns this structure array.

{
    Time    : 1567736576000,     // A timestamp, accurate to the millisecond, the same format as the result obtained by Javascript's newDate().GetTime()
    Open    : 1000,              // opening price
    High    : 1500,              // highest price
    Low     : 900,               // lowest price
    Close   : 1200,              // closing price
    Volume  : 1000000            // Trading volume
}
Order

Order structure, returned by exchange.GetOrder(), exchange.GetOrders() function.

{
    Info        : {...},         // After requesting the exchange interface, the original data of the exchange interface response, this attribute is not available during the backtest
    Id          : 123456,        // Transaction Unique ID
    Price       : 1000,          // Placing Order Price
    Amount      : 10,            // Placing Order Quantity
    DealAmount  : 10,            // Executed Volume
    AvgPrice    : 1000,          // The average transaction price, note that some exchanges do not provide this data(the setting is 0)
    Status      : 1,             // Order status, refer to the order status in the constant ORDER_STATE_CLOSED
    Type        : 0,             // Order type, refer to the order type ORDER_TYPE_BUY in the constant
    Offset      : 0              // In the order data of cryptocurrency futures and commodity futures, the order opening and closing direction, ORDER_OFFSET_OPEN is the opening position, ORDER_OFFSET_CLOSE is the closing direction
    ContractType : ""            // This attribute is "" for spot orders, and specific contract codes for futures orders
}
MarketOrder

Depth of market order, that is, exchange.GetDepth() returns the data structure of the elements in the Bids and Asks arrays in the data.

{
    Price   : 1000,              // Price
    Amount  : 1                  // Quantity
}
Depth

The market depth is returned by the exchange.GetDepth() function.

{
    Asks    : [...],             // Array of selling orders, array of MarketOrder, sorted by price from low to high
    Bids    : [...],             // Array of selling orders, array of MarketOrder, sorted by price from high to low
    Time    : 1567736576000      // Millisecond-level timestamp
}
Account

Account information, returned by the exchange.GetAccount() function.

{
    Info            : {...},     // After requesting the exchange interface, the original data of the exchange interface response, this attribute is not available during the backtest
    Balance         : 1000,      // Balance (RMB or USD, on Poloniex exchanges such as ETC_BTC, Balance refers to the amount of BTC, Stocks refers to the amount of ETC)
    FrozenBalance   : 0,         // Frozen balance
    Stocks          : 1,         // The number of BTC/LTC, the cryptocurrency spot is the balance of the current operable currency (minus the frozen currency), and the cryptocurrency futures are the contract's currently available margin (traditional commodity futures do not have this attribute)
    FrozenStocks    : 0          // Number of BTC/LTC frozen (traditional commodity futures do not have this attribute)
}
Position

For information about positions held in futures trading, this structure array is returned by the exchange.GetPosition() function.

{
    Info            : {...},     // After requesting the exchange interface, the original data of the exchange interface response, this attribute is not available during the backtest
    MarginLevel     : 10,        // Leverage Size
    Amount          : 100,       // holding position volume, OKEX contract exchange, indicates the number of contracts (integer and greater than 1, the number of contracts)
    FrozenAmount    : 0,         // Position freeze
    Price           : 10000,     // Average position price
    Profit          : 0,         // Position floating profit and loss (data currency unit: BTC/LTC, traditional futures unit: RMB, stocks do not support this field, Note: The OKEX contract refers to the realization of surplus in the case of a full position, not the holding position profit and loss, and the position by position refers to the holding position profit and loss)
    Type            : 0,         // PD_LONG is a long position (closed with closebuy_today in CTP), PD_SHORT is a short position (closed with closesell_today in CTP), (in CTP futures) PD_LONG_YD is a yesterday long position (closed with closebuy), PD_SHORT_YD is a yesterday short position (closed with closesell)
    ContractType    : "quarter", // Commodity futures are contract codes, stocks are 'Exchange code_Stock code', the specific parameter SetContractType's incoming type
    Margin          : 1          // Margin occupied by positions
}

Global Function

Version()

Version(), Returns the current version number of the system, a string value, such as 3.0. Return value: string type.

Sleep(Millisecond)

Sleep(Millisecond)sleep function makes the program pause for a period of time. Parameter value: Millisecond is of type number. The parameter unit is in milliseconds, for example: Sleep(1000) is sleep for one second.

Note: When writing strategies using the Python language, the Sleep(Millisecond) function should be used for operations that wait for a time such as the polling interval. It is not recommended to use the time library function time.time(second) in Python. Because after using the time.time(second) function in the strategy, the strategy program will actually wait for a certain number of seconds (the number of seconds in the second parameter setting), it will make the backtest progress very slow.

IsVirtual()

IsVirtual(), to determine whether it is a simulated backtest. Return value: bool type. The simulated backtest status returns true, and the real market returns false.

Mail(…)

Mail(smtpServer, smtpUsername, smtpPassword, mailTo, title, body), send mail function. Parameter value: all are of type string. Return value: bool type, true is returned after successful transmission.

smtpServer is the sending mailbox smtp, smtpUsername is the mailbox account, smtpPassword is the mailbox password, mailTo is the acceptance mailbox account, title is the title, body is the content. E.g:

function main(){
    Mail("smtp.163.com", "asdf@163.com", "password", "111@163.com", "title", "body")
}
def main():
    Mail("smtp.163.com", "asdf@163.com", "password", "111@163.com", "title", "body")
void main() {
    Mail("smtp.163.com", "asdf@163.com", "password", "111@163.com", "title", "body");
}

Note: Alibaba Cloud server may block some ports, so that the mail cannot be sent out. If you need to change the port, you can directly add the port number in the first parameter: For example: qq’s smtp.qq.com:587, the port test is available.

If an error occurs: unencrypted connection, you need to modify the Mail function smtpServer parameter to: format ssl://xxxxx.com:xxx, for example, the SMTP ssl method of QQ mailbox: ssl://smtp.qq.com:465 or: format smtp://xxxxx.com:xxx.

SetErrorFilter(…)

SetErrorFilter(RegEx), error message filtering. Parameter value: string type. Errors matched by this regular expression will not be uploaded to the log system, and can be called multiple times (filtered logs are not written to the database file of the corresponding robot ID in logs/robot in the docker directory, to prevent frequent error reporting Cause the database file to expand)

function main() {
    SetErrorFilter("502:|503:|tcp|character|unexpected|network|timeout|WSARecv|Connect|GetAddr|no such|reset|http|received|EOF|reused")
}
def main():
    SetErrorFilter("502:|503:|tcp|character|unexpected|network|timeout|WSARecv|Connect|GetAddr|no such|reset|http|received|EOF|reused")
`