Type/to search
8
Follow
1361
Followers
FMZ定量化に基づく注文同期管理システムの設計(1)
Original
Created 2022-02-14 19:46:30  Updated 2025-05-16 16:36:53
 11
 2243

img

FMZ定量化に基づく注文同期管理システムの設計(1)

FMZ ライブラリの以前の記事では、いくつかの順序と位置の同期戦略を設計しました。

これらは、参照アカウントと同期アカウントを 1 つの戦略にまとめ、注文とポジションを管理および同期するためのものです。今日は、別の設計を試してみます。FMZ 定量取引プラットフォームの強力な拡張 API インターフェイスに基づいて、注文同期管理システムを設計します。

デザインのアイデア

まず第一に、良い提案とニーズが必要です。上記の 2 つの注文とポジションの同期戦略には、明らかな問題点がいくつかあります。それらについて一緒に説明しましょう。

    1. 同期戦略の実装者は、参照アカウントの交換 API キーと同期アカウントの交換 API キーを持っている必要があります。
      この質問の使用シナリオは、他の取引所アカウントが自分のアカウントの 1 つをフォローしても問題がないということです。ただし、参照アカウントと同期アカウントの所有者が同じでない場合は面倒です。セキュリティ上の懸念から、同期されたアカウントの所有者が自分の取引所アカウントの API キーを提供したがらない場合があります。しかし、API KEY を提供せずに同期的に注文するにはどうすればよいでしょうか?

    解決:
    FMZの拡張APIインターフェースを使用すると、同期アカウントの所有者(フォロワー)は、FMZ定量取引プラットフォームを登録し、戦略を実行するだけで済みます(この記事で設計されたシステムでは、订单同步管理系统(Synchronous Server)戦略(実際の市場)。次に、FMZ拡張API KEY(取引所アカウントのAPI KEYではないことに注意してください)と注文同期管理システム(同期サーバー)のリアルタイムIDを参照アカウントの所有者(注文を持ち込む人)に提供します。 。
    アカウント所有者(注文者)の実際の注文を参照する場合(この記事で設計したシステムの場合)订单同步管理系统类库(Single Server))がシグナルを送信すると、同期されたアカウント所有者の実際のアカウントが取引シグナルを受信し、その後自動的に注文を出します。

    1. 多くの開発者はより優れた戦略を持っていますが、上記の 2 つの過去の注文とポジションの同期戦略を使用することはできません。なぜなら、そのためには、独自の戦略をこれらの同期戦略と統合する必要があり、戦略を全面的に見直す必要があるかもしれないため、時間と労力がかかるからです。成熟した戦略の一部を注文同期機能に直接アップグレードする良い方法はありますか?
      解決:
      注文同期テンプレートライブラリを設計することができます(この記事で設計したシステム订单同步管理系统类库(Single Server)ストラテジー)により、参照アカウントの所有者(注文を受ける人)は、このテンプレートライブラリを自分のストラテジーに直接埋め込むことで、注文とポジションの同期機能を実現できます。
    1. 余分な実数順序を 1 つ減らします。
      最後の問題点は、上で説明した 2 つの過去の注文とポジションの同期戦略を使用する場合です。参照口座(単一口座)のポジションを監視するには、追加のリアル口座を開設する必要があります。
      解決:
      テンプレート ライブラリを使用して、参照アカウント戦略に機能を埋め込みます。

したがって、このシステムは 2 つの部分で構成されます。

  1. 注文同期管理システムクラスライブラリ(シングルサーバー)
  2. 注文同期管理システム(同期サーバー)

要件が明確になったので、設計を始めましょう。

設計 1: 注文同期管理システム クラス ライブラリ (単一サーバー)

これは戦略ではないことに注意してください。これは FMZ のテンプレート クラス ライブラリです。テンプレート クラス ライブラリの概念は FMZ API ドキュメントで検索できるので、ここでは詳細には触れません。

テンプレートライブラリコード:

javascript
// 全局变量 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) { // 开仓 var tradeDirection = type == PD_LONG ? "buy" : "sell" // 发送信号 msg = symbol + "," + ct + "," + tradeDirection + "," + Math.abs(delta) } else if (delta < 0) { // 平仓 var tradeDirection = type == PD_LONG ? "closebuy" : "closesell" if (nowAmount <= 0) { Log("未检测到持仓") return } // 发送信号 msg = symbol + "," + ct + "," + tradeDirection + "," + Math.abs(delta) } else { throw "错误" } if (msg) { _.each(fmzExtendApis, function(extendApiConfig) { var ret = sendCommandRobotMsg(extendApiConfig[keyName_robotId], extendApiConfig[keyName_extendAccessKey], extendApiConfig[keyName_extendSecretKey], msg) Log("调用CommandRobot接口,", "label:", extendApiConfig[keyName_label], ", msg:", msg, ", ret:", ret) Sleep(1000) }) } } $.PosMonitor = function(exIndex, symbol, ct) { var ts = new Date().getTime() var ex = exchanges[exIndex] // 判断ex类型 var exName = ex.GetName() var isFutures = exName.includes("Futures_") var exType = isFutures ? "futures" : "spot" if (!isFutures) { throw "仅支持期货跟单" } if (exType == "futures") { // 缓存 symbol ct var buffSymbol = ex.GetCurrency() var buffCt = ex.GetContractType() // 切换到对应的交易对、合约代码 ex.SetCurrency(symbol) if (!ex.SetContractType(ct)) { throw "SetContractType failed" } // 监控持仓 var keyInitRefPosAmount = "refPos-" + exIndex + "-" + symbol + "-" + ct // refPos-exIndex-symbol-contractType var initRefPosAmount = mapInitRefPosAmount[keyInitRefPosAmount] if (!initRefPosAmount) { // 没有初始化数据,初始化 mapInitRefPosAmount[keyInitRefPosAmount] = getPosAmount(_C(ex.GetPosition), ct) initRefPosAmount = mapInitRefPosAmount[keyInitRefPosAmount] } // 监控 var nowRefPosAmount = getPosAmount(_C(ex.GetPosition), ct) // 计算仓位变动 var longPosDelta = nowRefPosAmount.long - initRefPosAmount.long var shortPosDelta = nowRefPosAmount.short - initRefPosAmount.short // 检测变动 if (!(longPosDelta == 0 && shortPosDelta == 0)) { // 执行多头动作 if (longPosDelta != 0) { Log(ex.GetName(), ex.GetLabel(), symbol, ct, "执行多头跟单,变动量:", longPosDelta) follow(nowRefPosAmount, symbol, ct, PD_LONG, longPosDelta) } // 执行空头动作 if (shortPosDelta != 0) { Log(ex.GetName(), ex.GetLabel(), symbol, ct, "执行空头跟单,变动量:", shortPosDelta) follow(nowRefPosAmount, symbol, ct, PD_SHORT, shortPosDelta) } // 执行跟单操作后,更新 mapInitRefPosAmount[keyInitRefPosAmount] = nowRefPosAmount } // 恢复 symbol ct ex.SetCurrency(buffSymbol) ex.SetContractType(buffCt) } else if (exType == "spot") { // 现货 } } $.getTbl = function() { var tbl = { "type" : "table", "title" : "同步数据", "cols" : [], "rows" : [] } // 构造表头 tbl.cols.push("监控账户:refPos-exIndex-symbol-contractType") tbl.cols.push(`监控持仓:{"时间戳":xxx,"多头持仓量":xxx,"空头持仓量":xxx}`) _.each(fmzExtendApis, function(extendApiData, index) { tbl.cols.push(keyName_robotId + "-" + index) }) // 写入数据 _.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 } // 引用该模板类库的策略调用范例 function main() { // 清除所有日志 LogReset(1) // 切换到OKEX 模拟盘测试 exchanges[0].IO("simulate", true) // 设置合约 exchanges[0].SetCurrency("ETH_USDT") exchanges[0].SetContractType("swap") // 定时交易时间间隔 var tradeInterval = 1000 * 60 * 3 // 三分钟交易一次,用于观察跟单信号 var lastTradeTS = new Date().getTime() while (true) { // 策略其它逻辑... // 用于测试的模拟交易触发 var ts = new Date().getTime() if (ts - lastTradeTS > tradeInterval) { Log("模拟带单策略发生交易,持仓变化", "#FF0000") exchanges[0].SetDirection("buy") exchanges[0].Buy(-1, 1) lastTradeTS = ts } // 使用模板的接口函数 $.PosMonitor(0, "ETH_USDT", "swap") // 可以设置多个监控,监控带单策略上的不同的exchange对象 var tbl = $.getTbl() // 显示状态栏 LogStatus(_D(), "\n" + "`" + JSON.stringify(tbl) + "`") Sleep(1000) } }

設計は非常にシンプルで、このクラス ライブラリには 2 つの機能があります。 FMZプラットフォーム上のプログラマティック取引戦略が参照する場合订单同步管理系统类库(Single Server)テンプレートライブラリの後。この戦略では次の機能を使用できます。

  • $.PosMonitor
    この機能は、戦略内の取引オブジェクトのポジション変更を監視し、テンプレートのパラメータで設定された実際の市場に取引シグナルを送信します: 注文同期管理システム クラス ライブラリ (シングル サーバー)。

  • $.getTbl
    監視された同期データを返します。

使用例は次の場所にあります: 注文同期管理システムクラスライブラリ (シングルサーバー) テンプレートmain関数内:

javascript
// 引用该模板类库的策略调用范例 function main() { // 清除所有日志 LogReset(1) // 切换到OKEX 模拟盘测试 exchanges[0].IO("simulate", true) // 设置合约 exchanges[0].SetCurrency("ETH_USDT") exchanges[0].SetContractType("swap") // 定时交易时间间隔 var tradeInterval = 1000 * 60 * 3 // 三分钟交易一次,用于观察跟单信号 var lastTradeTS = new Date().getTime() while (true) { // 策略其它逻辑... // 用于测试的模拟交易触发 var ts = new Date().getTime() if (ts - lastTradeTS > tradeInterval) { Log("模拟带单策略发生交易,持仓变化", "#FF0000") exchanges[0].SetDirection("buy") exchanges[0].Buy(-1, 1) lastTradeTS = ts } // 使用模板的接口函数 $.PosMonitor(0, "ETH_USDT", "swap") // 可以设置多个监控,监控带单策略上的不同的exchange对象 var tbl = $.getTbl() // 显示状态栏 LogStatus(_D(), "\n" + "`" + JSON.stringify(tbl) + "`") Sleep(1000) } }

テンプレート ライブラリ自体も実際の戦略を作成することができ、通常はテンプレート ライブラリをテストするために使用されます。たとえば、このテンプレートのテスト。テンプレートを理解できるmain関数はあなた自身の戦略です。main関数。

OKEXシミュレーションディスクテストを使用するためのテストコードが書かれています。FMZでOKEXシミュレーションディスクAPI KEYを参照アカウント(注文あり)として設定し、メイン関数でシミュレーションディスクへの切り替えを開始する必要があります。次に、取引ペアを ETH_USDT に設定し、契約を永久(スワップ)に設定します。次に、while ループを入力します。戦略取引のトリガーをシミュレートするために、サイクル内で 3 分ごとに注文が配置されます。 whileループは$.PosMonitor(0, "ETH_USDT", "swap")この関数の最初のパラメータは0として渡され、監視交換を示します。[[0] この交換オブジェクトは、ETH_USDT 取引ペアとスワップ契約を監視します。それから電話する$.getTbl()チャート情報を取得するには、LogStatus(_D(), "\n" + "" + JSON.stringify(tbl) + "")ステータス バーにチャート データを表示できるようにします。

つまり、このテンプレートを参照するポリシーで使用する限り、$.PosMonitor(0, "ETH_USDT", "swap")、この戦略には、特定の商品の位置を監視し、位置の変化に基づいてメッセージを送信する機能を備えることができます。

テストの前に説明してください订单同步管理系统类库(Single Server)戦略パラメータ設計:
テンプレート インターフェース機能を使用して、戦略アップグレードに単一の機能を持たせる方法について説明しました。では、位置が変わったときに信号は誰に送信されるのでしょうか?
この質問が誰に送られるかは、订单同步管理系统类库(Single Server)設定するパラメータ。

img

5 つのパラメーターがあり、最大 5 回のプッシュをサポートしていることがわかります (増やす必要がある場合は拡張できます)。パラメーターのデフォルトは空の文字列であり、処理されないことを意味します。設定文字列の形式: label、robotId、accessKey、secretKey

  • label
    同期されたアカウントのラベルは、特定のアカウントをマークするために使用され、名前は任意に設定できます。

  • robotId
    同期アカウントの所有者によって作成された実ID订单同步管理系统(Synchronous Server)実際のトランザクションの ID。

  • accessKey
    FMZの拡張APIアクセスキー

  • secretKey
    FMZの拡張API secretKey

次に簡単なテストを行います。

注文同期管理システムクラスライブラリ(シングルサーバー)実ディスク操作:

img

注文同期管理システム (同期サーバー) が信号を受信しました:
注文同期管理システム (同期サーバー) の設計はまだ完了していません。まずは、トランザクションを実行せず、シグナルのみを出力する簡単なコードで実装してみましょう。

注文同期管理システム(同期サーバー)の一時コード:

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

img

同期アカウント所有者の実際のアカウントが情報を受信したことがわかります。ETH_USDT,swap,buy,1
このように、次のステップは、情報内の取引ペア、契約コード、取引方向、数量に応じて取引を自動的に追跡することです。

現在のところ订单同步管理系统(Synchronous Server)これは単なる一時的なコードであり、次号ではその設計について引き続き検討します。

Related Recommendations
Comment
All comments (11)

    要实现跟单,还是需要两个实盘,一个是类库实盘,一个是订单管理系统实盘

    4 years ago

    您可能没看明白文章,这个类库是一个工具,可以在带单者策略行直接嵌入,然后这个策略就有带单功能了,就会给设置好的跟单账户发信息,跟单机器人就会收到消息跟单了。
    简单说就是这样的场景。

    4 years ago

    按教程弄的,显示配置错误

    4 years ago

    要看具体报什么错误信息。

    4 years ago

    错误 configs error!,在订单同步管理系统类库(Single Server)中,把带单者实盘和2个KEY都填进去了,然后再实盘中引用了订单同步管理系统类库(Single Server),报错,错误 configs error!

    4 years ago

    可以看下文章,配置信息: 标签,实盘ID,accesskey,secretkey 。 报这个错误应该就是您信息配置错了,您再检查下。注意使用英文逗号间隔。

    4 years ago

    错误 configs error!

    4 years ago

    反向跟单需要改哪些参数

    4 years ago

    需要改策略。

    4 years ago

    自己跟单自己也要开两个实盘,一个发信号一个收信号,这两个能合并一起实盘用么

    4 years ago

    代码公开的,您可以根据需求修改一下,就可以实现。

    4 years ago
  • 1
iPhone Download
Forums
PINE Language
© 2015 - ∞ INVENTOR PTE LTD (SG)