Konstruktion eines auf FMZ Quant basierenden Systems zur Verwaltung der Auftragssynchronisierung (1)

Schriftsteller:Lydia., Erstellt: 2022-11-07 10:20:01, Aktualisiert: 2023-09-15 20:45:23

img

Konstruktion eines auf FMZ Quant basierenden Systems zur Verwaltung der Auftragssynchronisierung (1)

In früheren Artikeln in FMZs Bibliothek haben wir mehrere Arten von Synchronisationsstrategien für Ordnung und Position entwickelt.

Diese verwalten Referenzkonten und synchronisierte Konten in einer Strategie, um Order- und Positionssynchronisierung zu erreichen.

Entwurfsideen

Zuerst brauchen wir einige gute Vorschläge und Bedürfnisse. Die beiden vorherigen Ordnung und Position Synchronisation Strategien oben, die mehrere offensichtliche Mängel haben, die wir gemeinsam diskutieren werden.

    1. Benutzer von Synchronisierungsstrategien müssen den Austausch API KEY des Referenzkontos und den Austausch API KEY des Synchronisierungskontos haben. Dieses Problem ist in Ordnung für die Nutzungssituation, in der die anderen Exchange-Konten des Benutzers seinem eigenen Konto folgen. Es kann jedoch für die Situation, in der das Referenzkonto und das Synchronisierungskonto nicht der gleiche Eigentümer sind, problematisch sein. Manchmal möchte der Eigentümer des synchronisierten Kontos aus Sicherheitsgründen den API-Key seines eigenen Exchange-Kontos nicht bereitstellen, aber wie können die Bestelltransaktionen ohne Bereitstellung des API-Key synchronisiert werden?

    Lösungen: Mit der erweiterten API-Schnittstelle von FMZ muss der Inhaber des synchronisierten Kontos (Orderfollower) nur ein Konto auf der FMZ Quant Trading Platform registrieren und dann eine Strategie ausführen (im in diesem Artikel entworfenen System:Order Synchronous ServerStrategie in Real Bot). Dann geben Sie einfach den FMZ erweiterten API KEY (beachten Sie, dass es nicht der API KEY des Austauschkontos ist) und die Order Synchronous Server real bot ID an den Eigentümer des Referenzkontos (Order Leader). Wenn der Eigentümer des Referenzkontos (der Auftragsnachfolger) einen echten Bot (denOrder Synchronization Management System Class Library (Single Server)In diesem Artikel wird ein Signal gesendet, wird der echte Bot des Synchronisierungskontoinhabers das Handelssignal empfangen und automatisch den nachfolgenden Auftrag erteilen.

    1. Viele Entwickler haben gute Strategien, aber sie können die 2 oben beschriebenen Strategien zur Synchronisierung der Vergangenheit nicht verwenden. Weil sie ihre eigenen Strategien mit diesen synchronisierten Strategien integrieren müssen, und die Strategien müssen möglicherweise drastisch geändert werden, was viel Arbeit und Mühe kosten wird. Gibt es eine gute Möglichkeit, einige Ihrer ausgereiften Strategien direkt auf die Funktion zur Synchronisierung der Reihenfolge zu aktualisieren? Lösungen: Sie können eine Synchronisierungsvorlage-Klassenbibliothek (dieOrder Synchronization Management System Class Library (Single Server)Strategie im in diesem Artikel entworfenen System), so daß der Eigentümer des Referenzkontos (Order-Leader) diese Vorlage-Klassenbibliothek direkt in seine eigene Strategie einbetten kann, um die Funktion der Reihenfolge- und Positionssynchronisierung zu erreichen.
    1. Reduzieren Sie einen weiteren echten Bot. Der letzte Nachteil ist, dass, wenn Sie die 2 vergangenen Aufträge verwenden, Positionen Synchronisierungsstrategie oben beschrieben. Lösungen: Verwenden Sie die Template-Klassenbibliothek, um Funktionen in die Referenzkonto-Strategie einzubauen.

Das System besteht also aus zwei Teilen:

  1. Klassenbibliothek für das System zur Verwaltung der Auftragssynchronisierung (Single Server)
  2. System zur Verwaltung der Auftragssynchronisierung (Synchronous Server)

Sobald wir unsere Bedürfnisse definiert haben, fangen wir an zu entwerfen!

Entwurf 1: Klassenbibliothek für das System zur Verwaltung von Auftragssynchronisierungen (Single Server)

Beachten Sie, dass dies keine Strategie ist. Es handelt sich um eine Template-Klasse-Bibliothek von FMZ. Das Konzept einer Template-Klasse-Bibliothek kann in der FMZ API-Dokumentation gesucht werden und wir werden es nicht wiederholen.

Code der Template-Klassenbibliothek:

// 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

        // detect changes
        if (!(longPosDelta == 0 && shortPosDelta == 0)) {
            // Perform long positions
            if (longPosDelta != 0) {
                Log(ex.GetName(), ex.GetLabel(), symbol, ct, "Perform long position-following, changes in volume:", longPosDelta)
                follow(nowRefPosAmount, symbol, ct, PD_LONG, longPosDelta)
            }
            // Perform short positions
            if (shortPosDelta != 0) {
                Log(ex.GetName(), ex.GetLabel(), symbol, ct, "Perform short position-following, changes in volume:", shortPosDelta)
                follow(nowRefPosAmount, symbol, ct, PD_SHORT, shortPosDelta)
            }

            // Update after performing the order-following operation
            mapInitRefPosAmount[keyInitRefPosAmount] = nowRefPosAmount
        }

        // restore symbol ct
        ex.SetCurrency(buffSymbol)
        ex.SetContractType(buffCt)
    } else if (exType == "spot") {
        // Spots
    }
}

$.getTbl = function() {
    var tbl = {
        "type" : "table", 
        "title" : "synchronization of data", 
        "cols" : [], 
        "rows" : []
    }
    // construct the table headers
    tbl.cols.push("monitor the account: refPos-exIndex-symbol-contractType")
    tbl.cols.push(`monitor the position: {"timestamp":xxx,"long positions":xxx,"short positions":xxx}`)
    _.each(fmzExtendApis, function(extendApiData, index) {
        tbl.cols.push(keyName_robotId + "-" + index)
    })
    
    // Write data in
    _.each(mapInitRefPosAmount, function(initRefPosAmount, key) {
        var arr = [key, JSON.stringify(initRefPosAmount)]
        _.each(fmzExtendApis, function(extendApiData) {
            arr.push(extendApiData[keyName_robotId])
        })
        tbl.rows.push(arr)
    })

    return tbl
}

// Example of the strategy call that references the template class library
function main() {
    // Clear all logs
    LogReset(1)

    // Switch to OKEX demo to test
    exchanges[0].IO("simulate", true)

    // Set the contract
    exchanges[0].SetCurrency("ETH_USDT")
    exchanges[0].SetContractType("swap")

    // Timed trading interval
    var tradeInterval = 1000 * 60 * 3        // Trade for every three minutes to observe the order-following signals
    var lastTradeTS = new Date().getTime()
    
    while (true) {
        // Other logic of the strategy...

        // Simulated trading triggers for testing
        var ts = new Date().getTime()
        if (ts - lastTradeTS > tradeInterval) {
            Log("Trade the simulation order-leading strategies, position changes", "#FF0000")
            exchanges[0].SetDirection("buy")
            exchanges[0].Buy(-1, 1)
            lastTradeTS = ts
        }

        // Interface functions that use templates
        $.PosMonitor(0, "ETH_USDT", "swap")    // Multiple monitors can be set up to monitor different exchange objects on the order-following strategy  
        var tbl = $.getTbl()
        
        // Display status bar
        LogStatus(_D(), "\n" + "`" + JSON.stringify(tbl) + "`")
        Sleep(1000)
    }
}

Das Design ist sehr einfach, die Klassenbibliothek hat 2 Funktionen.Order Synchronization Management System Class Library (Single Server). Dann kann die Strategie die folgenden Funktionen verwenden.

  • $. Positor-Monitor Zweck dieser Funktion ist es, die Positionsänderungen der Austauschobjekte in der Strategie zu überwachen und dann Handelssignale an den echten Bot-Markt zu senden, der in den Parametern der Vorlage: Order Synchronization Management System class library (Single Server) festgelegt ist.

  • $. GetTbl Zurück zu den überwachten Synchronisierungsdaten.

Ein Beispiel für die Verwendung ist in dermainFunktion der Vorlage Klassenbibliothek (Single Server):

// Example of the strategy call that references the template class library
function main() {
    // Clear all logs
    LogReset(1)

    // Switch to OKEX demo to test
    exchanges[0].IO("simulate", true)

    // Set the contract
    exchanges[0].SetCurrency("ETH_USDT")
    exchanges[0].SetContractType("swap")

    // Timed trading interval
    var tradeInterval = 1000 * 60 * 3        // Trade for every three minutes to observe the order-following signals
    var lastTradeTS = new Date().getTime()
    
    while (true) {
        // Other logic of the strategy...

        // Simulated trading triggers for testing
        var ts = new Date().getTime()
        if (ts - lastTradeTS > tradeInterval) {
            Log("Trade the simulation order-leading strategies, position changes", "#FF0000")
            exchanges[0].SetDirection("buy")
            exchanges[0].Buy(-1, 1)
            lastTradeTS = ts
        }

        // Interface functions by using templates
        $.PosMonitor(0, "ETH_USDT", "swap")    // Multiple monitors can be set up to monitor different exchange objects on the order-following strategy  
        var tbl = $.getTbl()
        
        // Display status bar
        LogStatus(_D(), "\n" + "`" + JSON.stringify(tbl) + "`")
        Sleep(1000)
    }
}

Eine Template-Klassenbibliothek kann auch einen Strategie-Real-Bot selbst erstellen, der normalerweise verwendet wird, um die Template-Klassenbibliothek zu testen, wie zum Beispiel die Prüfung der Vorlage.mainFunktion in einer Vorlage istmainSie ist eine Funktion einer Ihrer eigenen Strategien.

Der Testcode wird mit dem OKEX-Demo geschrieben, um zu testen, müssen Sie den OKEX-Demo-API-Key auf FMZ als Referenzkonto (Order-Leading) konfigurieren, und er beginnt in der Hauptfunktion auf Demo zu wechseln. Setzen Sie dann das Handelspaar auf ETH_USDT und setzen Sie den Vertrag auf Swap. Dann tritt er in eine While-Schleife ein. In der Schleife wird alle 3 Minuten ein Auftrag platziert, um das Auslösen von Strategie-Transaktionen zu simulieren.$.PosMonitor(0, "ETH_USDT", "swap")Wenn die ETH-Funktion in der while-Schleife aufgerufen wird, wird der erste Parameter dieser Funktion auf 0 übergeben, was bedeutet, dass die Exchange-Objekt-Austausch[0] überwacht wird, das ETH_USDT-Handelspaar überwacht wird, der Swap-Kontrakt.$.getTbl()Um Informationen über die Diagramme zu erhalten, werdenLogStatus(_D(), "\n" + "`" + JSON.stringify(tbl) + "`")um die auf der Statusleiste angezeigten Diagrammdaten zu erstellen.

Also können wir sehen, dass wir die Strategie haben die Fähigkeit, die Positionen einer bestimmten Spezies zu überwachen, und die Position ändert sich, um Nachrichten zu senden, indem Sie$.PosMonitor(0, "ETH_USDT", "swap")In einer Strategie, die auf die Vorlage verweist.

Vor dem Testen werden wir die Strategieparameter desOrder Synchronization Management System Class Library (Single Server)- Ich weiß. Wir haben gerade darüber gesprochen, wie man die Schnittstellenfunktion einer Vorlage nutzt, um eine Strategie zu aktualisieren, um eine Funktion der Bestellführung zu haben. Die Frage, wen man schicken soll, wird durch die Parameter derOrder Synchronization Management System Class Library (Single Server).

img

Wir können sehen, dass es 5 Parameter gibt, die bis zu 5 Pushes unterstützen (es kann von selbst erweitert werden, wenn es erhöht werden muss), die Standardparameter sind leere Zeichenfolgen, das heißt, nicht verarbeitet.

  • Etikett Ein Etikett für ein Synchronisierungskonto, es wird verwendet, um ein Etikett für ein Konto mit einem Namen zu setzen, das nach Belieben festgelegt werden kann.

  • RobotId Roboter-ID, die ID desOrder Synchronous ServerEin echter Bot, der vom Besitzer des synchronen Kontos erstellt wurde.

  • Zugriffsschlüssel Erweiterter API-Zugriff FMZ-Schlüssel

  • Geheimer Schlüssel Erweiterter API-Geheimschlüssel von FMZ

Der vorübergehende Code für das System zur Verwaltung der Auftragssynchronisierung (Synchronous Server):

function main() {
    LogReset(1)
    while (true) {
        var cmd = GetCommand()
        if (cmd) {
            // cmd: ETH_USDT,swap,buy,1
            Log("cmd: ", cmd)
        }
        Sleep(1000)
    }
}

img

Wir können sehen, dass der echte Bot des synchronisierten Kontoinhabers die Nachricht erhielt:ETH_USDT,swap,buy,1- Ich weiß. Dann wird es uns ermöglichen, unsere eigenen automatischen Auftrag-nach dem nächsten Schritt basierend auf den trading Paare, Vertrag Codes, Handel Richtungen und Menge in der Information.

Bislang haben dieOrder Synchronization Management System (Synchronous Server)ist der temporäre Code, werden wir seinen Entwurf in der nächsten Ausgabe weiter erforschen.


Verwandt

Mehr