Design of Order Synchronization Management System Based on FMZ Quant (1-1)

in #fmz7 months ago

In previous articles in FMZ's library, we have designed several kinds of synchronization strategies for order and position.

Design Ideas

    1. First, we need some good suggestions and needs. The two previous order and position synchronization strategies above, which have several obvious shortcomings, which we will discuss together.

Users of synchronization strategies real bot must have the exchange API KEY of the reference account, and the exchange API KEY of the synchronization account.
This issue is fine for the usage situation where one's other exchange accounts follow his or her own account. However, it can be troublesome for the situation where the reference account and the sync account are not the same owner. Sometimes the owner of the synchronized account does not want to provide the API KEY of his own exchange account for security reasons, but how to synchronize the order transactions without providing the API KEY?
Solutions:
Use the FMZ's extended API interface, the owner of the synchronized account (order follower) only needs to register an account on FMZ Quant Trading Platform, then run a strategy (in the system designed in this article: Order Synchronous Server Strategy in Real Bot). Then just provide the FMZ extended API KEY (note that it is not the API KEY of the exchange account) and the Order Synchronous Server real bot ID to the owner of the reference account (order leader).
When the reference account owner's (order follower's) real bot (the Order Synchronization Management System Class Library (Single Server) in the system designed in this article) sends a signal, the synchronization account owner's real bot will receive the trade signal and place the subsequent order automatically.

    1. Many developers have good strategies, but they cannot use the 2 past order and position synchronization strategies described above. Because they need to integrate their own strategies with these synchronized strategies, and the strategies may need to be changed drastically, which will cost a lot of work and effort. Is there a good way to upgrade some of your mature strategies directly to the order synchronization function?
      Solutions:
      You can design an order synchronization template class library (the Order Synchronization Management System Class Library (Single Server) strategy in the system designed in this article), so that the owner of the reference account (order-leader) can embed this template class library into his own strategy directly to achieve the function of order and position synchronization.
    1. Reduce an additional real bot.
      The last shortcoming is that if you use the 2 past orders, positions synchronization strategy described above. It is necessary to open an additional real bot to monitor the positions of reference account (account for order leaders).
      Solutions:
      Use the template class library to embed functionality in the reference account strategy.
      So the system consists of 2 parts:
  1. Order synchronization management system class library (Single Server)
  2. Order synchronization management system (Synchronous Server)

Once we've defined our needs, let's start designing!

Design 1: Order synchronization management system class library (Single Server)

Note that this is not a strategy. It is a template class library of FMZ. The concept of a template class library can be searched in the FMZ API documentation and we will not repeat it again.

Template class library code:

// Global variables
var keyName_label = "label"
var keyName_robotId = "robotId"
var keyName_extendAccessKey = "extendAccessKey"
var keyName_extendSecretKey = "extendSecretKey"
var fmzExtendApis = parseConfigs([config1, config2, config3, config4, config5])
var mapInitRefPosAmount = {}

function parseConfigs(configs) {
    var arr = []
    _.each(configs, function(config) {
        if (config == "") {
            return 
        }
        var strArr = config.split(",")
        if (strArr.length != 4) {
            throw "configs error!"
        }
        var obj = {}
        obj[keyName_label] = strArr[0]
        obj[keyName_robotId] = strArr[1]
        obj[keyName_extendAccessKey] = strArr[2]
        obj[keyName_extendSecretKey] = strArr[3]
        arr.push(obj)
    })
    return arr 
}

function getPosAmount(pos, ct) {
    var longPosAmount = 0
    var shortPosAmount = 0
    _.each(pos, function(ele) {
        if (ele.ContractType == ct && ele.Type == PD_LONG) {
            longPosAmount = ele.Amount
        } else if (ele.ContractType == ct && ele.Type == PD_SHORT) {
            shortPosAmount = ele.Amount
        }
    })
    var timestamp = new Date().getTime()
    return {ts: timestamp, long: longPosAmount, short: shortPosAmount}
}

function sendCommandRobotMsg (robotId, accessKey, secretKey, msg) {
    // https://www.fmz.com/api/v1?access_key=xxx&secret_key=yyyy&method=CommandRobot&args=[186515,"ok12345"]
    var url = "https://www.fmz.com/api/v1?access_key=" + accessKey + "&secret_key=" + secretKey + "&method=CommandRobot&args=[" + robotId + ',"' + msg + '"]'
    Log(url)
    var ret = HttpQuery(url)
    return ret 
}

function follow(nowPosAmount, symbol, ct, type, delta) {
    var msg = ""
    var nowAmount = type == PD_LONG ? nowPosAmount.long : nowPosAmount.short
    if (delta > 0) {
        // open the position
        var tradeDirection = type == PD_LONG ? "buy" : "sell"
        // send signals
        msg = symbol + "," + ct + "," + tradeDirection + "," + Math.abs(delta)        
    } else if (delta < 0) {
        // close the position
        var tradeDirection = type == PD_LONG ? "closebuy" : "closesell"
        if (nowAmount <= 0) {
            Log("no positions found")
            return 
        }
        // send signals
        msg = symbol + "," + ct + "," + tradeDirection + "," + Math.abs(delta)
    } else {
        throw "error"
    }
    if (msg) {
        _.each(fmzExtendApis, function(extendApiConfig) {
            var ret = sendCommandRobotMsg(extendApiConfig[keyName_robotId], extendApiConfig[keyName_extendAccessKey], extendApiConfig[keyName_extendSecretKey], msg)
            Log("call the CommandRobot interface, ", "label:", extendApiConfig[keyName_label], ",  msg:", msg, ",  ret:", ret)
            Sleep(1000)
        })
    }
}

$.PosMonitor = function(exIndex, symbol, ct) {    
    var ts = new Date().getTime()
    var ex = exchanges[exIndex]
    // judge the type of ex
    var exName = ex.GetName()
    var isFutures = exName.includes("Futures_")
    var exType = isFutures ? "futures" : "spot"
    if (!isFutures) {
        throw "only future-following is supported"
    }

    if (exType == "futures") {
        // caching symbol ct
        var buffSymbol = ex.GetCurrency()
        var buffCt = ex.GetContractType()

        // switch to the corresponding contract pair, contract code
        ex.SetCurrency(symbol)
        if (!ex.SetContractType(ct)) {
            throw "SetContractType failed"
        }

        // monitor positions
        var keyInitRefPosAmount = "refPos-" + exIndex + "-" + symbol + "-" + ct    // refPos-exIndex-symbol-contractType
        var initRefPosAmount = mapInitRefPosAmount[keyInitRefPosAmount]
        if (!initRefPosAmount) {
            // no initialization data, initialize it
            mapInitRefPosAmount[keyInitRefPosAmount] = getPosAmount(_C(ex.GetPosition), ct)
            initRefPosAmount = mapInitRefPosAmount[keyInitRefPosAmount]
        }

        // monitor
        var nowRefPosAmount = getPosAmount(_C(ex.GetPosition), ct)
        // calculate the position changes
        var longPosDelta = nowRefPosAmount.long - initRefPosAmount.long
        var shortPosDelta = nowRefPosAmount.short - initRefPosAmount.short

To be continued...

Coin Marketplace

STEEM 0.29
TRX 0.12
JST 0.032
BTC 63867.81
ETH 3135.89
USDT 1.00
SBD 3.84