The Advantages of Using FMZ's Extended API for Efficient Group Control Management in Quantitative Trading

The Advantages of Using FMZ's Extended API for Efficient Group Control Management in Quantitative Trading

·

5 min read

With the popularization and development of quantitative trading, investors often need to manage a large number of live accounts, which brings great challenges to trading decisions, monitoring and execution. In order to improve management efficiency and reduce operational difficulty, traders on FMZ can use FMZ's extended API for group control management. In this article, we will discuss the advantages of using FMZ's extended API in quantitative trading and how to achieve efficient group control management.

Many users have their own customer live accounts that need managing and maintaining. When there are many customer live accounts, a more convenient way is needed for managing them (as few as dozens or as many as hundreds). FMZ provides a powerful extended API; using this for group control management has become an ideal choice.

Centralized Monitoring

Through FMZ's extended API, you can centrally monitor the trading activities and asset conditions of all live accounts. Whether it is checking the positions of each account, historical trading records, or real-time monitoring of the profit and loss status of accounts, all of them can be achieved.

// Global variable
var isLogMsg = true   // Control whether the log is printed
var isDebug = false   // Debug mode
var arrIndexDesc = ["all", "running", "stop"]
var descRobotStatusCode = ["In idle", "Running", "Stopping", "Exited", "Stopped", "Strategy error"]
var dicRobotStatusCode = {
    "all" : -1,
    "running" : 1,
    "stop" : 4,
}

// Extended log function
function LogControl(...args) {
    if (isLogMsg) {
        Log(...args)
    }
}

// FMZ extended API call function
function callFmzExtAPI(accessKey, secretKey, funcName, ...args) {
    var params = {
        "version" : "1.0",
        "access_key" : accessKey,
        "method" : funcName,
        "args" : JSON.stringify(args),
        "nonce" : Math.floor(new Date().getTime())
    }

    var data = `${params["version"]}|${params["method"]}|${params["args"]}|${params["nonce"]}|${secretKey}`
    params["sign"] = Encode("md5", "string", "hex", data)

    var arrPairs = []
    for (var k in params) {
        var pair = `${k}=${params[k]}`
        arrPairs.push(pair)
    }
    var query = arrPairs.join("&")

    var ret = null
    try {
        LogControl("url:", baseAPI + "/api/v1?" + query)
        ret = JSON.parse(HttpQuery(baseAPI + "/api/v1?" + query))
        if (isDebug) {
            LogControl("Debug:", ret)
        }
    } catch(e) {
        LogControl("e.name:", e.name, "e.stack:", e.stack, "e.message:", e.message)
    }
    Sleep(100)  // Control frequency
    return ret 
}

// Obtain all live trading information of the specified strategy Id.
function getAllRobotByIdAndStatus(accessKey, secretKey, strategyId, robotStatusCode, maxRetry) {
    var retryCounter = 0
    var length = 100
    var offset = 0
    var arr = []

    if (typeof(maxRetry) == "undefined") {
        maxRetry = 10
    }

    while (true) {
        if (retryCounter > maxRetry) {
            LogControl("Exceeded the maximum number of retries", maxRetry)
            return null
        }
        var ret = callFmzExtAPI(accessKey, secretKey, "GetRobotList", offset, length, robotStatusCode)
        if (!ret || ret["code"] != 0) {
            Sleep(1000)
            retryCounter++
            continue
        }

        var robots = ret["data"]["result"]["robots"]
        for (var i in robots) {
            if (robots[i].strategy_id != strategyId) {
                continue
            }
            arr.push(robots[i])
        }

        if (robots.length < length) {
            break
        }
        offset += length
    }

    return arr 
}

function main() {
    var robotStatusCode = dicRobotStatusCode[arrIndexDesc[robotStatus]]
    var robotList = getAllRobotByIdAndStatus(accessKey, secretKey, strategyId, robotStatusCode)
    if (!robotList) {
        Log("Failed to obtain live trading data")
    }

    var robotTbl = {"type": "table", "title": "live trading list", "cols": [], "rows": []}
    robotTbl.cols = ["live trading Id", "live trading name", "live trading status", "strategy name", "live trading profit"]

    _.each(robotList, function(robotInfo) {
        robotTbl.rows.push([robotInfo.id, robotInfo.name, descRobotStatusCode[robotInfo.status], robotInfo.strategy_name, robotInfo.profit])
    })

    LogStatus(_D(), "`" + JSON.stringify(robotTbl) + "`")
}

Strategy parameter design:

Running on live trading:

One-click Execution

Group control management makes it very convenient to execute transactions with one-click. You can buy, sell, and close positions on multiple live trading accounts simultaneously without having to open each account individually. This not only improves execution efficiency, but also reduces the possibility of operational errors.

After obtaining the list of live trading accounts, we can send commands to these accounts and perform a series of predetermined operations. For example: clearing positions in the live account, pausing protection in the live account, switching modes in the live account. All these can be achieved through FMZ's extended API CommandRobot.

As we continue writing code, we just need to add some interactions and calls to the extended API interface CommandRobot in our main function:

function main() {
    var robotStatusCode = dicRobotStatusCode[arrIndexDesc[robotStatus]]
    var robotList = getAllRobotByIdAndStatus(accessKey, secretKey, strategyId, robotStatusCode)
    if (!robotList) {
        Log("Failed to obtain live trading data")
    }

    var robotTbl = {"type": "table", "title": "live trading list", "cols": [], "rows": []}
    robotTbl.cols = ["live trading Id", "live trading name", "live trading status", "strategy name", "live trading profit"]

    _.each(robotList, function(robotInfo) {
        robotTbl.rows.push([robotInfo.id, robotInfo.name, descRobotStatusCode[robotInfo.status], robotInfo.strategy_name, robotInfo.profit])
    })

    LogStatus(_D(), "`" + JSON.stringify(robotTbl) + "`")

    while(true) {
        LogStatus(_D(), ", Waiting to receive interactive commands", "\n", "`" + JSON.stringify(robotTbl) + "`")

        var cmd = GetCommand()
        if (cmd) {
            var arrCmd = cmd.split(":")
            if (arrCmd.length == 1 && cmd == "coverAll") {
                _.each(robotList, function(robotInfo) {
                    var strCmd = "Clearance"               // You can define the required message format
                    if (robotInfo.status != 1) {     // Only the "live" trading platform can receive commands.
                        return 
                    }
                    var ret = callFmzExtAPI(accessKey, secretKey, "CommandRobot", parseInt(robotInfo.id), strCmd)
                    LogControl("Send command to the live trading board with id: ", robotInfo.id, ":", strCmd, ", execution result:", ret)
                })
            }
        }
        Sleep(1000)
    }
}

The group control strategy sent instructions to "Test 1 A" and "Test 1 B".

Strategy Synchronization

With FMZ's extended API, you can easily implement batch modifications of strategy parameters, and batch start or stop live trading.

Summary

In quantitative trading, by using FMZ's extended API for group control management, traders can monitor, execute and adjust multiple live accounts more efficiently. This centralized management method not only improves operational efficiency, but also helps to better implement risk control and strategy synchronization.

For traders managing a large number of live accounts, FMZ's extended API provides them with a powerful and flexible tool that makes quantitative trading more convenient and controllable.

From: https://blog.mathquant.com/2023/11/20/the-advantages-of-using-fmzs-extended-api-for-efficient-group-control-management-in-quantitative-trading.html