奧克手把手教你用JS對接FMZ擴展API

簡介

大家好,我是“奧克量化”。由於前段時間,我開發的行情趨勢提醒【監控大盤】廣受大家的喜愛,並且有【奧克量化】同名服務號的同步提醒,讓新老韭菜在行情趨勢的判斷上,有了新的參考。藉此熱度,開始着手對接FMZ的擴展API,來實現機器人之間的消息通訊,並直接推送行情提醒到指定機器人中。本文舉例兩個應用場景,藉此拋磚引玉,希望大家可以多多開發出好玩的東東來…

本篇主要介紹:
一、開發者如何通過JS語言對接FMZ的擴展API。(本文以GetNodeList方法爲例)
二、案例一:使用擴展API的CommandRobot方法,實現監控大盤機器人與其他機器人之間的消息通訊。
三、案例二:使用擴展API的GetRobotDetail方法,實現多個機器人數據的統一監控和展示。

一、使用JS對接FMZ的擴展API

1)、申請AccessKey和SecretKey(以下我們簡稱AK、SK)。
我們在FMZ官網【賬號設置】->【API接口】->【創建新的ApiKey】的菜單中進行申請,然後獲取到一組AK、SK並記錄下來。(FMZ的AK、SK不像是交易所只有創建第一次可見,在FMZ中我們可以隨時在【API接口】菜單中查看我們AK、SK的全量數據)

2)、根據擴展API的文檔進行開發
首先來看請求API的關鍵幾步
1、FMZ API接口:

https://www.fmz.com/api/v1

2、請求基本參數

{
    'version'   : '1.0',                                //自定義版本號
    'access_key': '8a148320e0bxxxxxxxxxxxxxx19js99f',   //AK
    'method'    : 'GetNodeList',                        //具體調用的方法
    'args'      : [],                                   //具體method算法的參數列表
    'nonce'     : 1516292399361,                        //時間戳,單位毫秒
    'sign'      : '085b63456c93hfb243a757366600f9c2'    //簽名(需要根據上面5個參數加密獲取,下面有講)
}

3、完整的請求URL以問號傳參的形式拼接

以GetNodeList方法爲例
https://www.fmz.com/api/v1?
access_key=8a148320e0bxxxxxxxxxxxxxx19js99f&
nonce=1516292399361&
args=%5B%5D&
sign=085b63456c93hfb243a757366600f9c2&
version=1.0&
method=GetNodeList

4、簽名方式

按照如下順序進行參數拼接後,使用MD5加密算法加密字符串,並轉換爲十六進制數據字符串值,該值作爲參數sign的值。
version + "|" + method + "|" + args + "|" + nonce + "|" + secretKey

5、綜上所述,有以下代碼
源碼地址:【奧克量化】-JS對接FMZ擴展API Demo

var URL = "https://www.fmz.com/api/v1?";
var AK = "b3a53d3XXXXXXXXXXXXXXXXXXX866fe5";//這裏替換成你自己的AccessKey
var SK = "1d9ddd7XXXXXXXXXXXXXXXXXXX85be17";//這裏替換成你自己的SecretKey

function main() {
    //獲取5個基礎參數對象
    var param = getParam("1.0.0",AK,getArgs());
    Log("param:",param);
    //獲取拼接參數md5加密後的結果
    var md5Result = md5(param);
    //賦值加密結果到基礎參數對象中
    param.sign = md5Result;
    //獲取請求api的URL
    var finalUrl = getFinalUrl(param);
    Log("finalUrl:",finalUrl);
    //執行請求並打印結果
    var info = HttpQuery(finalUrl);
    Log("info:",info);
}

//獲取基礎5個參數的對象
function getParam(version,ak,args){
    return {
        'version': version,
        'access_key': ak,
        'method': 'GetNodeList',
        'args': JSON.stringify(args),
        'nonce': new Date().getTime()
    }
}

//執行md5加密
function md5(param){
    var paramUrl = param.version+"|"+param.method+"|"+param.args+"|"+param.nonce+"|"+SK
    Log("paramUrl:",paramUrl);
    return Hash("md5", "hex", paramUrl)
}

//獲取最終請求URL
function getFinalUrl(param){
    return URL+"access_key="+AK+"&nonce="+param.nonce+"&args="+param.args+"&sign="+param.sign+"&version="+param.version+"&method="+param.method;
}

//js中不支持...args的命名方式,所以改用arguments關鍵字獲取參數數組
function getArgs(){
    return [].slice.call(arguments);
}

案例二:使用擴展API的CommandRobot方法實現機器人之間的消息通訊

在上述代碼的基礎上,我們來使用CommandRobot方法實現機器人之間的消息通訊。

首先我們來看下CommandRobot(RobotId, Cmd)方法所需要的兩個參數

參數名 類型 含義
RobotId int 機器人ID,可以用GetRobotList(…)獲取或者在機器人詳情頁獲得
Cmd String 向機器人發送的消息

知道了參數的意思,那我們接下來就來實現這個調用方法。

1、在機器人詳情頁獲取到機器人ID:

2、實現獲取Cmd消息的方法

//獲取消息頭信息
function getMessageBody(toUserName,msgType,content){
    return ({
        "toUserName":toUserName,//發送給誰
        "fromUserName":AOKE_INFO,//消息來源
        "createTime": new Date().getTime(),//當前時間戳
        "msgType":msgType,//消息類型
        "content":content,//消息內容
        "msgId":Math.random().toString(36).slice(-8)//消息ID
    })
}

//獲取消息體趨勢信息(消息頭content字段的數據)
function getCtaDate(symbol,timeCycle,direction,nowCycleTime){
    return {
        "symbol":symbol,//交易幣種
        "timeCycle":timeCycle,//趨勢週期
        "direction":direction,//當前進入的方向,0:看空,1:看多
        "createTime":new Date().getTime(),//當前時間戳
        "nowCycleTime":nowCycleTime//當前進入的週期起始時間
    }
}

3、修改發送消息代碼

//發送消息前先獲取消息
var sendMessage = getMessageBody("測試對象",'CTARemind',getCtaDate('BTC_USDT','120','0','2020-05-1620:00:00'));

//把機器人ID和消息體通過getArgs()方法獲取,並傳入基礎參數。
var param = getParam("1.0.0",AK,getArgs(17777,sendMessage));

4、執行main方法,發送消息後,使用GetCommand()方法獲取消息

function main(){
    while(true) { 
        var cmd = GetCommand()
        if (cmd) { 
            Log(cmd)
        }
        Sleep(1000) 
    }
}

發送消息成功:

接收消息成功:

案例三:使用擴展API的GetRobotList和GetRobotDetail方法實現機器人的數據監控和展示。

同樣的,我們先來看下兩個方法的參數說明
GetRobotList(offset, length, robotStatus, label):

參數名 類型 含義
offset int 查詢的頁碼
length int 查詢頁的數據長度
robotStatus int 傳-1代表獲取全部
label String 自定義標籤,可以篩選出這個標籤的所有機器人

GetRobotDetail(RobotId):

參數名 類型 含義
RobotId int 機器人ID

1、通過GetRobotList方法獲取Robot列表

//獲取機器人列表信息
var robotListJson = getAPIInfo('GetRobotList',getArgs(OFF_SET,PAGE_LENGTH,-1));
var robotList = robotListJson.data.result.robots;

2、獲取機器人詳情信息

//獲取機器人詳情信息
var robotDetailJson = getAPIInfo('GetRobotDetail',getArgs(robotId));
var robotDetail = robotDetailJson.data.result.robot;

3、控制檯輸出表格數據

function getLogPrient(infoArr){
    return table = {
            type: 'table',
            title: '奧克量化的機器人展示',
            cols: ['機器人ID','機器人名稱','策略名稱','下次扣費時間','已經消耗時間ms','已經消耗金額CNY','最近活躍時間','是否公開'],
            rows: infoArr
        };
}

4、綜上所述,有以下代碼
源碼地址:【奧克量化】-使用擴展API獲取機器人的信息並展示

var URL = "https://www.fmz.com/api/v1?";
var AK = "b3a53d3XXXXXXXXXXXXXXXXXXX866fe5";//這裏替換成你自己的AccessKey
var SK = "1d9ddd7XXXXXXXXXXXXXXXXXXX85be17";//這裏替換成你自己的SecretKey
var OFF_SET = 0;//查詢的頁碼下標
var PAGE_LENGTH = 5;//查詢頁的數據長度

function main() {
    LogReset();
    while(true){
        //獲取機器人列表信息
        var robotListJson = getAPIInfo('GetRobotList',getArgs(OFF_SET,PAGE_LENGTH,-1));
        //取出機器人列表信息
        var robotList = robotListJson.data.result.robots;
        //創建展示機器人信息的數組
        var infoArr = new Array();
        var infoArr_index = 0;
        for (index = 0; index < robotList.length; index++) {
            var robot = robotList[index];
            //取出當前循環到的機器人ID
            var robotId = robot.id;
            //獲取機器人詳情信息
            var robotDetailJson = getAPIInfo('GetRobotDetail',getArgs(robotId));
            var robotDetail = robotDetailJson.data.result.robot;
            //轉換詳情爲數組對象
            var arr = getLogPrientItem(robotDetail);
            infoArr[infoArr_index] = arr;
            infoArr_index++;
        }
        Log("infoArr:",infoArr);
        LogStatus('`' + JSON.stringify(getLogPrient(infoArr)) + '`');
        Sleep(30000);
    }
}

function getLogPrient(infoArr){
    return table = {
            type: 'table',
            title: '奧克量化的機器人展示',
            cols: ['機器人ID','機器人名稱','策略名稱','下次扣費時間','已經消耗時間ms','已經消耗金額CNY','最近活躍時間','是否公開'],
            rows: infoArr
        };
}

//通過參數獲取API信息
function getAPIInfo(method,dateInfo){
    //獲取5個基礎參數對象
    var param = getParam("1.0.0",AK,method,dateInfo);
    //Log("param:",param);
    //獲取拼接參數md5加密後的結果
    var md5Result = md5(param);
    //賦值加密結果到基礎參數對象中
    param.sign = md5Result;
    //獲取請求api的URL
    var finalUrl = getFinalUrl(param);
    //Log("finalUrl:",finalUrl);
    //執行請求並打印結果
    var info = HttpQuery(finalUrl);
    //Log("info:",info);
    return JSON.parse(info);
}

//獲取基礎5個參數的對象
function getParam(version,ak,method,args){
    return {
        'version': version,
        'access_key': ak,
        'method': method,
        'args': JSON.stringify(args),
        'nonce': new Date().getTime()
    }
}

//執行md5加密
function md5(param){
    var paramUrl = param.version+"|"+param.method+"|"+param.args+"|"+param.nonce+"|"+SK
    //Log("paramUrl:",paramUrl);
    return Hash("md5", "hex", paramUrl)
}

//獲取最終請求URL
function getFinalUrl(param){
    return URL+"access_key="+AK+"&nonce="+param.nonce+"&args="+param.args+"&sign="+param.sign+"&version="+param.version+"&method="+param.method;
}

//js中不支持...args的命名方式,所以改用arguments關鍵字獲取參數數組
function getArgs(){
    return [].slice.call(arguments);
}

//獲取展示詳情對象'機器人ID','機器人名稱','策略名稱','下次扣費時間','已經消耗時間ms','已經消耗金額CNY','最近活躍時間','是否公開'],
function getLogPrientItem(robotDetail){
    var itemArr = new Array();
    var iteArr_index = 0;
    itemArr[iteArr_index++] = robotDetail.id;
    itemArr[iteArr_index++] = robotDetail.name;
    itemArr[iteArr_index++] = robotDetail.strategy_name;
    itemArr[iteArr_index++] = robotDetail.charge_time;
    itemArr[iteArr_index++] = robotDetail.charged;
    itemArr[iteArr_index++] = robotDetail.consumed/1e8;
    itemArr[iteArr_index++] = robotDetail.refresh;
    itemArr[iteArr_index++] = robotDetail.public == 0?"已公開":"未公開";
    return itemArr;
}

效果展示:

結語

在實際的擴展中,還可以實現更多更好玩的功能。例如使用CommandRobot方法讓每一個機器人都向A機器人發送心跳檢測,如果A機器人發現某臺機器沒有了心跳,但是機器人還在運行中,那麼就可以通過FMZ服務號進行報警。如此,就可以避免例如_C()死循環等導致程序假死場景的報警。
希望通過我這次的拋磚引玉,FMZ平臺可以有更多、更好玩的功能被大家開發、開源。
最後感謝FMZ平臺以及夢總、超總、Z大等各位大神的支持和幫助。感謝~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章