리소스 로딩... 로딩...

FMZ API 지침

저자:제로, 제작: 2020-04-20 10:19:00, 업데이트: 2023-04-12 14:44:56

거래명령의 통지 가격: 1000, // 주문 가격; 시장 주문의 이 속성은 0 또는 -1일 수 있습니다. 금액: 10, // 주문 금액; 시장 주문의 이 속성은 동전 번호가 아니라 돈 금액이 될 수 있습니다. DealAmount: 10, // 실행량; 플랫폼 인터페이스에서 이러한 종류의 데이터를 제공하지 않는 경우, 아마도 0을 채우기 위해 사용 AVGPrice: 1000, // 평균 실행 가격; 일부 플랫폼이 이 데이터를 제공하지 않는 것을 참고하십시오. 상태: 1, // 순서 상태; ORDER_STATE_CLOSED와 같은 상수에서 순서 상태를 참조 타입: 0, // 명령어 타입; ORDER_TYPE_BUY와 같은 상수에서 명령어 타입을 참조 오프셋: 0 // 암호화폐 선물의 오더 데이터의 오더 오픈 및 클로즈 방향;ORDER_OFFSET_OPEN는 오픈 포지션이고 ORDER_OFFSET_CLOSE는 클로즈 방향입니다 ContractType : // 이 속성은 즉석 주문, 즉 null 문자열을 위해; 선물 주문의 속성은 특정 계약 코드입니다 ♪ ♪


##### MarketOrder

Market depth order, that is, ```exchange.GetDepth()``` returns the data structure of the elements in the **Bids** and **Asks** arrays in the data.

```javascript
{
    Price   : 1000,              // Price
    Amount  : 1                  // Volume
}
깊이

시장 깊이는 함수로 반환됩니다.exchange.GetDepth().

{
    Asks    : [...],             // The array of sell orders, namely MarketOrder array, sorted by price from low to high
    Bids    : [...],             // The array of buy orders, namely MarketOrder array, sorted by price from high to low
    Time    : 1567736576000      // Millisecond-level timestamp
}
계좌

계정 정보, 함수에서 반환exchange.GetAccount()구조에서 반환 된 데이터는 현재 설정 된 거래 쌍 및 계약 코드와 관련이 있습니다.

{
    Info            : {...},     // After requesting the platform interface, this attribute is not available in the raw data that the platform interface responds to, during the backtest
    Balance         : 1000,      // The available amount of quote currency; if the trading pair is BTC_USDT in the spot trading, "balance" refers to the current USDT amount. In the USDT-margined futures contract, "balance" refers to the available margin amount in USDT
    FrozenBalance   : 0,         // Here "balance" refers to the frozen amount of the assets for pending orders
    Stocks          : 1,         // The available amount of base currency; if the trading pair is BTC_USDT in the spot trading, "stocks" refers to the current BTC amount. In the crypto-margined futures contract, "stocks" refers to the available margin amount (base currency)
    FrozenStocks    : 0          // Here "stocks" refers to the frozen amount of the assets for pending orders
}
위치

미래에셋 거래에서 보유한 포지션에 대한 정보는배열이 중Position구조는 함수에서 반환됩니다exchange.GetPosition() function.

{
    Info            : {...},     // After requesting the platform interface, this attribute is not available in the raw data that the platform interface responds to, during the backtest
    MarginLevel     : 10,        // The leverage size of positions; if this data is not provided by the platform interface, fill in the data by calculation, possibly with errors
    Amount          : 100,       // Position volume; the contract quantity of positions is normally positive integer. Notice every platform might have different contract specifications, such as contract multiplier and value, etc., so the rules for ordering might be different; for example, Binance contract might order by 0.1
    FrozenAmount    : 0,         // The quantity of frozen positions, used as the number of temporary position freeze when close positions and pending orders
    Price           : 10000,     // Average position price; in principle, the attribute is the average price of the entire position (which does not involve in the settlement); if the platform interface does not provide the data, use the existing average position price of the platform to fill in (which involves in the settlement)
    Profit          : 0,         // Position floating profit and loss, namely the failure of realizing position profit and loss. If the platform interface does not provide the data, use other profit and loss data from the interface to fill in; the unit of the profit and loss values is the same as the unit of the current contract margin 

    Type            : 0,         // PD_LONG is a long position, while PD_SHORT is a short position
    ContractType    : "quarter", // Contract code; for more details, refer to the transmitted parameters in the description of the function "SetContractType"
    Margin          : 1          // Margin occupied by positions; if the platform interface does not provide the data, use 0 to fill in
}

암호화폐 선물에 대해,Position함수가 반환하는 구조 배열exchange.GetPosition()그 위치 데이터 구조의 속성에 대한 경우,FrozenAmount, Profit그리고Margin, 서로 다른 데이터 정의는 서로 다른 교환 객체에 의해 반환될 수 있습니다.exchange.GetPosition()예를 들어, 일부 거래소는 위치 동결 데이터를 포함하지 않습니다.FrozenAmount0입니다. 어떤 데이터를 계산해야 하는 경우, 당신은 속성에서 소스 데이터를 사용할 수 있습니다Info계산과 분석을 위해

세계적 기능

버전

Version()시스템의 현재 버전 번호를 반환합니다. 반환 값: 문자열 유형.

잠자리 (밀리초)

Sleep(Millisecond), 수면 기능, 일정 기간 동안 프로그램을 중지합니다. 매개 변수 값:Millisecond숫자 타입입니다. 매개 변수 단위는 밀리 초입니다. 예를 들어:Sleep(1000)한 초 동안 잠자리를 잤다는 뜻이죠. 1 밀리초 이하의 수면시간을 가진 지원 작업, 예를 들어 설정Sleep (0.1). 지원되는 최소 매개 변수는0.0000011나노초는1e-6 milliseconds.

참고: 전략이 작성될 때Python언어, 기능Sleep(Millisecond)투표 간격 및 대기 시간과 같은 작업을 위해 사용되어야 합니다.time.time(second)time도서관Python왜냐하면 함수를 사용할 때time.time(second)전략에서, 전략 프로그램은 실제로 몇 초 동안 기다립니다 (패라미터second즉, 매우 느린 전략 백테스트로 이어질 것입니다.

가상 (virtual)

IsVirtual(), 시뮬레이션된 백테스트인지 확인하기 위해 반환 값: bool 타입. 시뮬레이션된 백테스트 상태가 반환됩니다.true그리고 진짜 로봇이 돌아옵니다.false.

우편 ((...)

Mail(smtpServer, smtpUsername, smtpPassword, mailTo, title, body)메일 전송 함수입니다. 매개 변수 값: 모든 것은 문자열 유형입니다. 반환 값: bool 타입;true성공적으로 전송된 후에 반환됩니다.smtpServer보내는 우편함에 사용 됩니다.smtp; smtpUsername메일박스 계정입니다smtpPassword우편함의 STMP 비밀번호입니다.mailTo수신 메일박스 계정입니다title전송된 메일의 제목입니다.body전송된 우편의 내용입니다. 예를 들어:

function main(){
    Mail("smtp.163.com", "asdf@163.com", "password", "111@163.com", "title", "body")
}
def main():
    Mail("smtp.163.com", "asdf@163.com", "password", "111@163.com", "title", "body")
void main() {
    Mail("smtp.163.com", "asdf@163.com", "password", "111@163.com", "title", "body");
}
  • Mail_Go함수는 함수의 비동기 버전입니다Mail: 그 사용은 기능과 비슷합니다.exchange.Go.

    function main() {
        var r1 = Mail_Go("smtp.163.com", "asdf@163.com", "password", "111@163.com", "title", "body")
        var r2 = Mail_Go("smtp.163.com", "asdf@163.com", "password", "111@163.com", "title", "body")
        
        var ret1 = r1.wait()
        var ret2 = r2.wait()
        
        Log("ret1:", ret1)
        Log("ret2:", ret2)
    }
    
    # Not supported
    
    // Not supported
    

참고: 알리바바 클라우드 서버는 일부 포트를 차단하여 메일이 전송되지 않을 수 있습니다. 포트를 변경해야하는 경우 첫 번째 매개 변수에 직접 포트 번호를 추가할 수 있습니다.smtp.qq.com:587(QQmail), 포트는 테스트에 사용할 수 있습니다. 오류가 발생하면:unencrypted connection, 당신은 파라미터 포맷을 수정해야 합니다smtpServer함수에서Mail다음의 경우ssl://xxxxx.com:xxx예를 들어, SMTP ssl QQmail 방법:ssl://smtp.qq.com:465또는smtp://xxxxx.com:xxx.

SetErrorFilter (실점 필터 설정)

ErrorFilter(RegEx), 오류 로그 필터링. 매개 변수 값: 문자열 유형. 이 정규 표현식으로 일치하는 오류는 로그 시스템에 업로드되지 않으며 여러 번 호출 될 수 있습니다. 필터 로그는 자주 오류 보고로 인한 데이터베이스 파일 확장을 방지하기 위해 도커 콘텐츠의 로그 / 봇에서 해당 봇 ID의 데이터베이스 파일에 기록되지 않습니다.

function main() {
    SetErrorFilter("502:|503:|tcp|character|unexpected|network|timeout|WSARecv|Connect|GetAddr|no such|reset|http|received|EOF|reused")
}
def main():
    SetErrorFilter("502:|503:|tcp|character|unexpected|network|timeout|WSARecv|Connect|GetAddr|no such|reset|http|received|EOF|reused")
void main() {
    SetErrorFilter("502:|503:|tcp|character|unexpected|network|timeout|WSARecv|Connect|GetAddr|no such|reset|http|received|EOF|reused");
}

인터페이스의 오류 정보를 필터:

function main() {
    // Randomly check a non-existent order with ID 123; intentionally make the interface report an error
    var order = exchange.GetOrder("123")
    Log(order)
    // Filter http502 errors and GetOrder interface errors; after set the error filter, the second time to call GetOrder no longer reports errors
    SetErrorFilter("502:|GetOrder")
    order = exchange.GetOrder("123")
    Log(order)
}
def main():
    order = exchange.GetOrder("123")
    Log(order)
    SetErrorFilter("502:|GetOrder")
    order = exchange.GetOrder("123")
    Log(order)
void main() {
    TId orderId;
    Order order = exchange.GetOrder(orderId);
    Log(order);
    SetErrorFilter("502:|GetOrder");
    order = exchange.GetOrder(orderId);
    Log(order);
}

GetPid ((()

GetPid()bot 프로세스 ID를 반환합니다. 반환 값: 문자열 유형.

function main(){
    var id = GetPid()
    Log(id)
}
def main():
    id = GetPid()
    Log(id)
void main() {
    auto id = GetPid();
    Log(id);
}

GETLastError()

GetLastError()최신 오류 정보를 얻습니다. 일반적으로, 그것은 프로그램이 로그 시스템에 오류 정보를 자동으로 업로드 하기 때문에 사용 할 필요가 없습니다. 반환 값: 문자열 유형. 당신이 함수를 호출 한 후GetLastError(), 오류 캐시는 지워집니다; 다시 호출할 때, 마지막 기록된 오류 정보는 반환되지 않습니다.

function main(){
    // Because the order with ID number of 123 does not exist, an error is reported
    exchange.GetOrder("123")
    var error = GetLastError()
    Log(error)
}
def main():
    exchange.GetOrder("123")
    error = GetLastError()
    Log(error)
void main() {
    // The type of order ID: TId; so no string can be passed in, and we can trigger it by placing an order that does not meet the exchange specifications
    exchange.GetOrder(exchange.Buy(1, 1));
    auto error = GetLastError();
    Log(error);
}

GetCommand (() 를 받아보세요

GetCommand()인터랙티브 명령어 (utf-8) 를 얻는다. 전략 인터랙티브 인터페이스에서 전송된 명령어를 받아 캐시를 지우고, 명령어가 없으면 빈 문자열을 반환한다. 반환된 명령어 형식은button name: parameter; 인터랙티브 컨트롤에 매개 변수가 없다면 (예를 들어, 입력 상자 없이 버튼 컨트롤), 명령어는 버튼 이름입니다.

function main(){
    while(true) { 
        var cmd = GetCommand()
        if (cmd) { 
            Log(cmd)
        }
        Sleep(1000) 
    }
}
def main():
    while True:
        cmd = GetCommand()
        if cmd:
            Log(cmd)
        Sleep(1000)
void main() {
    while(true) {
        auto cmd = GetCommand();
        if(cmd != "") {
            Log(cmd);
        }
        Sleep(1000);
    }
}

기본 시스템에는 상호 작용 명령어를 기록하는 대기열 구조가 있습니다.GetCommand()호출되면, 큐에 먼저 입력하는 인터랙티브 명령어가 꺼집니다 (인터랙티브 명령어가 없다면, 빈 문자열입니다).

인터랙티브 컨트롤을 사용하는 예제; 전략 편집 인터페이스에 인터랙티브 컨트롤을 설정:

img

전략에서 상호 작용 코드를 설계합니다.

function main() {
    while (true) {
        LogStatus(_D())
        var cmd = GetCommand()
        if (cmd) {
            Log("cmd:", cmd)    
            var arr = cmd.split(":")
            if (arr[0] == "buy") {
                Log("Buy, the control without quantity")
            } else if (arr[0] == "sell") {
                Log("Sell, the control with quantity: ", arr[1])
            } else {
                Log("Other controls trigger:", arr)
            }
        }
        Sleep(1000)
    } 
}
def main():
    while True:
        LogStatus(_D())
        cmd = GetCommand()
        if cmd:
            Log("cmd:", cmd)
            arr = cmd.split(":")
            if arr[0] == "buy":
                Log("Buy, the control without quantity")
            elif arr[0] == "sell":
                Log("Sell, the control with quantity:", arr[1])
            else:
                Log("Other controls trigger:", arr)
        Sleep(1000)
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
using namespace std;
void split(const string& s,vector<string>& sv,const char flag = ' ') {
    sv.clear();
    istringstream iss(s);
    string temp;

    while (getline(iss, temp, flag)) {
        sv.push_back(temp);
    }
    return;
}

void main() {
    while(true) {
        LogStatus(_D());
        auto cmd = GetCommand();
        if (cmd != "") {
            vector<string> arr;
            split(cmd, arr, ':');
            if(arr[0] == "buy") {
                Log("Buy, the control without quantity");
            } else if (arr[0] == "sell") {
                Log("Sell, the control with quantity:", arr[1]);
            } else {
                Log("Other controls trigger:", arr);
            }
        }
        Sleep(1000);
    }
}

GetMeta (메타)

기능GetMeta()값을 반환합니다Meta전략 토큰이 생성될 때 쓰인 함수의 반환 값은 문자열 타입입니다. 응용 프로그램: 예를 들어, 전략은 다른 임차인에게 자산을 제한해야합니다. 참고: 전략 토큰이 생성되면Meta190 문자열을 초과할 수 없습니다. 함수는 실제 거래에만 적용되며 최신 도커가 필요합니다. 전략 토큰이 생성될 때 소스 데이터가 설정되지 않으면,GetMeta()null을 반환합니다.

신청서에서 증명된 관련 정보

function main() {
    // The largest assets value of quote currency allowed by the strategy
    
    // Get the metadata generated when the strategy token is established
    var level = GetMeta()
    
    // Check the corresponding conditions of "Meta"
    if (level == "level1") {
        // "-1" indicates no limitation 
        maxBaseCurrency = -1       
    } else if (level == "level2") {
        maxBaseCurrency = 10     
    } else if (level == "level3") {
        maxBaseCurrency = 1
    } else {
        maxBaseCurrency = 0.5
    }
    
    while(1) {
        Sleep(1000)
        var ticker = exchange.GetTicker()
        
        // Check the assets value
        var acc = exchange.GetAccount()
        if (maxBaseCurrency != -1 && maxBaseCurrency < acc.Stocks + acc.FrozenStocks) {
            // Stop the execution of the strategy trading logic 
            LogStatus(_D(), "level:", level, "The position exceeds the strategy token's using limitation, and stop the execution of the strategy trading logic!")
            continue
        }
        
        // Other trading logic
        
        // Export the information of status bar normally
        LogStatus(_D(), "level:", level, "The strategy runs normally! Ticker data: \n", ticker)
    }
}
def main():
    maxBaseCurrency = null
    level = GetMeta()
    
    if level == "level1":
        maxBaseCurrency = -1       
    elif level == "level2":
        maxBaseCurrency = 10     
    elif level == "level3":
        maxBaseCurrency = 1
    else:
        maxBaseCurrency = 0.5
    
    while True:
        Sleep(1000)
        ticker = exchange.GetTicker()        
        acc = exchange.GetAccount()
        if maxBaseCurrency != -1 and maxBaseCurrency < acc["Stocks"] + acc["FrozenStocks"]:
            LogStatus(_D(), "level:", level, "The position exceeds the strategy token's using limitation, and stop the execution of the strategy trading logic!")
            continue        
        
        # Other trading logic
        
        # Export the information of status bar normally
        LogStatus(_D(), "level:", level, "The strategy runs normally! Ticker data: \n", ticker)
void main() {
    auto maxBaseCurrency = 0.0;
    auto level = GetMeta();
    
    if (level == "level1") {
        maxBaseCurrency = -1;  
    } else if (level == "level2") {
        maxBaseCurrency = 10;
    } else if (level == "level3") {
        maxBaseCurrency = 1;
    } else {
        maxBaseCurrency = 0.5;
    }
    
    while(1) {
        Sleep(1000);
        auto ticker = exchange.GetTicker();  
        auto acc = exchange.GetAccount();
        if (maxBaseCurrency != -1 && maxBaseCurrency < acc.Stocks + acc.FrozenStocks) {
            // Stop the execution of the strategy trading logic
            LogStatus(_D(), "level:", level, "The position exceeds the strategy token's using limitation, and stop the execution of the strategy trading logic!");
            continue;
        }
        
        // Other trading logic
        
        // Export the information of status bar normally
        LogStatus(_D(), "level:", level, "The strategy runs normally! Ticker data: \n", ticker);
    }
}

다이얼...

Dial(Address, Timeout), 오리지널 소켓 액세스, 지원tcp, udp, tls그리고unix프로토콜, 파라미터 값:Address문자열 유형입니다. 단위는 두 번째입니다. 시간이 끝나면 함수Dial(...)빈 값을 반환합니다.

자세한 설명Address파라미터:

매개 변수 세부 정보
함수를 설정하는 매개 변수Dial 추가로 분리|정상 주소 다음의 기호:wss://ws.okx.com:8443/ws/v5/public■ 만약|매개 변수 문자열의 문자, 사용||분계자로 연결&예를 들어 ss5 대리 및 압축 매개 변수는 함께 설정됩니다.Dial("wss://ws.okx.com:8443/ws/v5/public|proxy=socks5://xxx:9999&compress=gzip_raw&mode=recv").
ws 프로토콜에서, 관련 데이터 압축 매개 변수:compress=parameter value 압축은 압축 방법입니다. 압축 매개 변수는gzip_raw그리고gzip, 등 gzip 메소드가 비표준 gzip인 경우 확장 메소드를 사용할 수 있습니다:gzip_raw, 즉, 설정 추가compress=gzip_raw분리 장치 뒤에|, 그리고&기호와 다음 모드 매개 변수를 분리합니다.
ws 프로토콜에서, 관련 데이터 압축 매개 변수:mode=parameter value 모드는 3가지 옵션을 포함하는 모드입니다.dual, send그리고recv. dual양방향으로 압축된 데이터를 보내고 수신합니다.send압축된 데이터를 전송하는 것입니다.recv압축된 데이터를 수신하고, 로컬로 압축을 해제하는 것입니다.
5 대리 설정에 대한 관련 매개 변수:proxy=parameter value proxy는 ss5 proxy 설정입니다. 매개 변수 값 형식:socks5://name:pwd@192.168.0.1:1080; name는 ss5 서버 사용자 이름; pwd는 ss5 서버 로그인 비밀번호; 1080는 ss5 서버의 포트
ws 프로토콜에서, 기본 자동 재연결을 설정하는 관련 매개 변수:reconnect=parameter value 재연결: 재연결을 설정할 것인지 여부reconnect=true다시 연결을 호출하는 것이 기본 설정입니다. 다시 연결하지 않는 것입니다.
ws 프로토콜에서, 기본 자동 재연결을 설정하는 관련 매개 변수:interval=parameter value 'interval'는 밀리 초에 표현된 재시험 간격입니다.interval=1000010초의 재시험 간격이고 기본 설정은 1초입니다.interval=1000.
ws 프로토콜에서, 기본 자동 재연결을 설정하는 관련 매개 변수:payload= parameter value payload는 ws가 다시 연결될 때 보내야 하는 구독 메시지입니다. 예를 들어:payload=okok.
function main(){
    // Dial supports tcp://, udp://, tls://, unix:// protocol, so you can add a parameter to specify the number of seconds to timeout
    var client = Dial("tls://www.baidu.com:443")  
    if (client) {
        // "Write" can be followed by a numeric parameter to specify the timeout, and "write" returns the number of bytes successfully sent
        client.write("GET / HTTP/1.1\nConnection: Closed\n\n")
        while (true) {
            // "Read" can be followed by a numeric parameter to specify the timeout, in millisecond. Return null to indicate error, timeout or closed socket
            var buf = client.read()
            if (!buf) {
                 break
            }
            Log(buf)
        }
        client.close()
    }
}
def main():
    client = Dial("tls://www.baidu.com:443")
    if client:
        client.write("GET / HTTP/1.1\nConnection: Closed\n\n")
        while True:
            buf = client.read()
            if not buf:
                break
            Log(buf)
        client.close()
void main() {
    auto client = Dial("tls://www.baidu.com:443");
    if(client.Valid) {
        client.write("GET / HTTP/1.1\nConnection: Closed\n\n");
        while(true) {
            auto buf = client.read();
            if(buf == "") {
                break;
            }
            Log(buf);
        }
        client.close();
    }
}

기능read다음의 매개 변수를 지원합니다.

  • 매개 변수가 전달되지 않을 때, 메시지가 나오기 전까지는 차단됩니다.ws.read().
  • 매개 변수를 전달할 때 대기 메시지의 타임아웃을 밀리초 단위로 지정합니다. 예를 들어:ws.read(2000)타임아웃을 2초 (2000 밀리초) 로 지정합니다.
  • 다음 두 가지 매개 변수는websocket: 매개 변수 전달-1즉, 어떤 메시지가 있는지 여부에 관계없이 즉시 반환하는 것을 의미합니다.ws.read(-1)- 그래요 매개 변수 전달-2메시지가 있는지 여부에 관계없이 즉시 반환하는 것을 의미합니다. 그러나 최신 메시지가 반환되며 버퍼에 있는 메시지는 폐기됩니다.ws.read(-2).

기능read()버퍼 설명: 만약 ws 프로토콜에 의해 전송되는 데이터가 전략 사이의 긴 간격이라면read()함수 호출을 하면 데이터 축적이 발생할 수 있으며 이 데이터는 버퍼에 저장됩니다. 버퍼 데이터 구조는 대기열이며 상한도는 2000입니다. 2000을 초과한 후 최신 데이터가 버퍼에 입력되고 가장 오래된 데이터가 지워집니다.

시나리오Read함수 매개 변수 매개 변수가 없습니다. 파라미터: -1 파라미터: -2 매개 변수: 2000 (단위: ms)
버퍼는 이미 데이터를 가지고 있습니다. 가장 오래된 데이터를 즉시 반환 가장 오래된 데이터를 즉시 반환 최신 데이터를 즉시 돌려주세요. 가장 오래된 데이터를 즉시 반환
버퍼에 데이터가 없습니다. 데이터가 차단되었을 때 데이터를 반환 즉시 null을 반환합니다 즉시 null을 반환합니다 2000ms를 기다립니다. 데이터가 없다면 null을 반환합니다. 데이터가 있다면 데이터를 반환합니다.
Ws 연결이 끊기거나 아래층이 다시 연결됩니다 read() 함수는 null, 즉: , 그리고 함수 write() 은 0을 반환합니다. 이 상황이 감지되면, 함수 close() 을 사용하여 연결을 닫을 수 있습니다. 자동으로 재연결을 설정하면 닫을 필요가 없으며 시스템의 하층 계층은 자동으로 재연결됩니다.
  • Wss (WebSocket) 프로토콜을 지원합니다 바이낸스 웹소켓 시장 인터페이스 접근:

    function main() {
        LogStatus("connecting...")
        // Access Binance websocket interface
        var client = Dial("wss://stream.binance.com:9443/ws/!ticker@arr")
        if (!client) {
            Log("connection failed, program exited")
            return
        }
        
        while (true) {
            // "read" only returns the obtained data after call "read" 
            var buf = client.read()      
            if (!buf) {
                break
            }
            var table = {
                type: 'table',
                title: 'Quote Chart',
                cols: ['Currency', 'Highest', 'Lowest', 'Buy One', 'Sell One', 'Last Executed Price', 'Volume', 'Update Time'],
                rows: []
            }
            var obj = JSON.parse(buf)
            _.each(obj, function(ticker) {
                table.rows.push([ticker.s, ticker.h, ticker.l, ticker.b, ticker.a, ticker.c, ticker.q, _D(ticker.E)])
            })
            LogStatus('`' + JSON.stringify(table) + '`')
        }
        client.close()
    }
    
    import json
    def main():
        LogStatus("connecting...")
        client = Dial("wss://stream.binance.com:9443/ws/!ticker@arr")
        if not client:
            Log("Connection failed, program exited")
            return 
        
        while True:
            buf = client.read()
            if not buf:
                break
            table = {
                "type" : "table", 
                "title" : "Quote Chart", 
                "cols" : ['Currency', 'Highest', 'Lowest', 'Buy One', 'Sell One', 'Last Executed Price', 'Volume', 'Update Time'], 
                "rows" : [] 
            }
            obj = json.loads(buf)
            for i in range(len(obj)):
                table["rows"].append([obj[i]["s"], obj[i]["h"], obj[i]["l"], obj[i]["b"], obj[i]["a"], obj[i]["c"], obj[i]["q"], _D(int(obj[i]["E"]))])
            LogStatus('`' + json.dumps(table) + '`')
        client.close()
    
    void main() {
        LogStatus("connecting...");
        auto client = Dial("wss://stream.binance.com:9443/ws/!ticker@arr");
        if(!client.Valid) {
            Log("Connection failed, program exited");
            return;
        }
        
        while(true) {
            auto buf = client.read();
            if(buf == "") {
                break;
            }
            json table = R"({
                "type" : "table", 
                "title" : "Quote Chart", 
                "cols" : ['Currency', 'Highest', 'Lowest', 'Buy One', 'Sell One', 'Last Executed Price', 'Volume', 'Update Time'], 
                "rows" : []
            })"_json;
            json obj = json::parse(buf);
            for(auto& ele : obj.items()) {
                table["rows"].push_back({ele.value()["s"], ele.value()["h"], ele.value()["l"], ele.value()["b"], ele.value()["a"], ele.value()["c"], 
                    ele.value()["q"], _D(ele.value()["E"])});
            }
            LogStatus("`" + table.dump() + "`");
        }
        client.close();
    }
    

    접근 OKX 웹소켓 시장 인터페이스:

    var ws = null 
    function main(){
          var param = {
            "op": "subscribe",
            "args": [{
                "channel": "tickers",
                "instId": "BTC-USDT"
            }]
        }
        // When call the function "Dial", specify "reconnect=true" and set to reconnect; specify "payload" as the message to be sent when reconnect. When websocket closes the connection, it will automatically reconnect and send the message
        ws = Dial("wss://ws.okx.com:8443/ws/v5/public|compress=gzip_raw&mode=recv&reconnect=true&payload="+ JSON.stringify(param))
        if(ws){
            ws.write(JSON.stringify(param))
            var pingCyc = 1000 * 20
            var lastPingTime = new Date().getTime()
            while(true){
                var nowTime = new Date().getTime()
                var ret = ws.read()
                Log("ret:", ret)
                if(nowTime - lastPingTime > pingCyc){
                    var retPing = ws.write("ping")
                    lastPingTime = nowTime
                    Log("send: ping", "#FF0000")
                }
                LogStatus("current time:", _D())
                Sleep(1000)
            }
        }
    }
    
    function onexit() {
        ws.close() 
        Log("exit")
    }
    
    import json
    import time
    
    ws = None
    def main():
        global ws 
        param = {
            "op": "subscribe",
            "args": [{
                "channel": "tickers",
                "instId": "BTC-USDT"
            }]
        }
        ws = Dial("wss://ws.okx.com:8443/ws/v5/public|compress=gzip_raw&mode=recv&reconnect=true&payload=" + json.dumps(param))
        if ws:
            pingCyc = 1000 * 20
            lastPingTime = time.time() * 1000
            while True:
                nowTime = time.time() * 1000
                ret = ws.read()
                Log("ret:", ret)
                if nowTime - lastPingTime > pingCyc:
                    retPing = ws.write("ping")
                    lastPingTime = nowTime
                    Log("send: ping", "#FF0000")
                LogStatus("current time:", _D())
                Sleep(1000)
    
    def onexit():
        ws.close()
        Log("exit")
    
    auto objWS = Dial("wss://ws.okx.com:8443/ws/v5/public|compress=gzip_raw&mode=recv&reconnect=true");  
    
    void main() {
            json param = R"({"op": "subscribe", "args": ["spot/ticker:ETH-USDT"]})"_json;
             "op": "subscribe",
            "args": [{
                "channel": "tickers",
                "instId": "BTC-USDT"
            }]
        })"_json;
        
        objWS.write(param.dump());
        if(objWS.Valid) {
            uint64_t pingCyc = 1000 * 20;
            uint64_t lastPingTime = Unix() * 1000;
            while(true) {
                uint64_t nowTime = Unix() * 1000;
                auto ret = objWS.read();
                Log("ret:", ret);
                if(nowTime - lastPingTime > pingCyc) {
                    auto retPing = objWS.write("ping");
                    lastPingTime = nowTime;
                    Log("send: ping", "#FF0000");
                }
                LogStatus("current time:", _D());
                Sleep(1000);
            }
        }
    }  
    
    void onexit() {
        objWS.close();
        Log("exit");
    }
    

    Huobi 웹소켓 시장 인터페이스에 액세스:

    var ws = null   
    
    function main(){
        var param = {"sub": "market.btcusdt.detail", "id": "id1"}
        ws = Dial("wss://api.huobi.pro/ws|compress=gzip&mode=recv&reconnect=true&payload="+ JSON.stringify(param))
        if(ws){
            while(1){
                var ret = ws.read()
                Log("ret:", ret)
                // Respond to heartbeat
                try {
                    var jsonRet = JSON.parse(ret)
                    if(typeof(jsonRet.ping) == "number") {
                        var strPong = JSON.stringify({"pong" : jsonRet.ping})
                        ws.write(strPong)
                        Log("respond ping, send pong:", strPong, "#FF0000")
                    }
                } catch(e) {
                    Log("e.name:", e.name, "e.stack:", e.stack, "e.message:", e.message)
                }
                
                LogStatus("current time:", _D())
                Sleep(1000)
            }
        }
    }  
    
    function onexit() {
        ws.close() 
        Log("execute function ws.close()")
    }
    
    import json
    ws = None  
    
    def main():
        global ws
        param = {"sub" : "market.btcusdt.detail", "id" : "id1"}
        ws = Dial("wss://api.huobi.pro/ws|compress=gzip&mode=recv&reconnect=true&payload=" + json.dumps(param))
        if ws:
            while True:
                ret = ws.read()
                Log("ret:", ret)              
                # Respond to heartbeat 
                try:
                    jsonRet = json.loads(ret)
                    if "ping" in jsonRet and type(jsonRet["ping"]) == int:
                        strPong = json.dumps({"pong" : jsonRet["ping"]})
                        ws.write(strPong)
                        Log("respond ping, send pong:", strPong, "#FF0000")
                except Exception as e:
                    Log("e:", e)
                    
                LogStatus("current time: ", _D())
                Sleep(1000)
        
    def onexit():
        ws.close()
        Log("execute function ws.close()")  
    
    using namespace std;
    void main() {
        json param = R"({"sub" : "market.btcusdt.detail", "id" : "id1"})"_json;
        auto ws = Dial("wss://api.huobi.pro/ws|compress=gzip&mode=recv&reconnect=true&payload=" + param.dump());
        if(ws.Valid) {
            while(true) {
                auto ret = ws.read();
                Log("ret:", ret);              
                // Respond to heartbeat
                try 
                {
                    auto jsonRet = json::parse(ret);
                    if(jsonRet["ping"].is_number()) {
                        json pong = R"({"pong" : 0})"_json;
                        pong["pong"] = jsonRet["ping"];
                        auto strPong = pong.dump();
                        ws.write(strPong);
                        Log("respond ping, send pong:", strPong, "#FF0000");
                    }
                } catch(exception &e) 
                {
                    Log("e:", e.what());
                }
                
                LogStatus("current time:", _D());
                Sleep(1000);
            }
        }
    }  
    
    void onexit() {
        // ws.close();
        Log("execute function ws.close()");
    }
    

    OKX에 접근하는 웹소켓 인터페이스의 확인 인터페이스:

      function getLogin(pAccessKey, pSecretKey, pPassphrase) {
        // Signature function for login
        var ts = (new Date().getTime() / 1000).toString()
        var login = {
            "op": "login",
            "args":[{
                "apiKey"    : pAccessKey,
                "passphrase" : pPassphrase,
                "timestamp" : ts,
                "sign" : exchange.HMAC("sha256", "base64", ts + "GET" + "/users/self/verify", pSecretKey)
            }]
        }    
        return login
    }    
    
    var client_private = null 
    function main() {
        // Because the read function adopts the timeout setting, the timeout error is filtered, otherwise there will be redundant error output
        SetErrorFilter("timeout")
        
        // Position channel subscription information
        var posSubscribe = {
            "op": "subscribe",
            "args": [{
                "channel": "positions",
                "instType": "ANY"
            }]
        }    
    
        var accessKey = "xxx"
        var secretKey = "xxx"
        var passphrase = "xxx"
    
        client_private = Dial("wss://ws.okx.com:8443/ws/v5/private")
        client_private.write(JSON.stringify(getLogin(accessKey, secretKey, passphrase)))
        Sleep(3000)  // When logging in, we cannot subscribe to private channels immediately, we need to wait for server response
        client_private.write(JSON.stringify(posSubscribe))
        if (client_private) {
            var lastPingTS = new Date().getTime()
            while (true) {
                var buf = client_private.read(-1)
                if (buf) {
                    Log(buf)
                }
                
                // Detect disconnection, reconnect
                if (buf == "" && client_private.write(JSON.stringify(posSubscribe)) == 0) {
                    Log("Disconnection detected, connection closed, reconnect")
                    client_private.close()
                    client_private = Dial("wss://ws.okx.com:8443/ws/v5/private")
                    client_private.write(JSON.stringify(getLogin(accessKey, secretKey, passphrase)))
                    Sleep(3000)
                    client_private.write(JSON.stringify(posSubscribe))
                }
                
                // Send heartbeat packets
                var nowPingTS = new Date().getTime()
                if (nowPingTS - lastPingTS > 10 * 1000) {
                    client_private.write("ping")
                    lastPingTS = nowPingTS
                }            
            }        
        }
    }    
    
    function onexit() {    
        var ret = client_private.close()
        Log("Close the connection!", ret)
    }
    
    import json
    import time
        
    def getLogin(pAccessKey, pSecretKey, pPassphrase):
        ts = str(time.time())
        login = {
            "op": "login",
            "args":[{
                "apiKey"    : pAccessKey,
                "passphrase" : pPassphrase,
                "timestamp" : ts,
                "sign" : exchange.HMAC("sha256", "base64", ts + "GET" + "/users/self/verify", pSecretKey)
            }]
        }
        return login     
    
    client_private = None 
    def main():
        global client_private
        SetErrorFilter("timeout")
        
        posSubscribe = {
            "op": "subscribe",
            "args": [{
                "channel": "positions",
                "instType": "ANY"
            }]
        }      
    
        accessKey = "xxx"
        secretKey = "xxx"
        passphrase = "xxx"
        
        client_private = Dial("wss://ws.okx.com:8443/ws/v5/private")
        client_private.write(json.dumps(getLogin(accessKey, secretKey, passphrase)))
        Sleep(3000)
        client_private.write(json.dumps(posSubscribe))
        if client_private:
            lastPingTS = time.time() * 1000
            while True:
                buf = client_private.read(-1)
                if buf:
                    Log(buf)
                
                if buf == "" and client_private.write(json.dumps(posSubscribe)) == 0:
                    Log("Disconnection detected, connection closed, reconnect")
                    ret = client_private.close()
                    client_private = Dial("wss://ws.okx.com:8443/ws/v5/private")
                    client_private.write(json.dumps(getLogin(accessKey, secretKey, passphrase)))
                    Sleep(3000)
                    client_private.write(json.dumps(posSubscribe))
                
                nowPingTS = time.time() * 1000
                if nowPingTS - lastPingTS > 10 * 1000:
                    client_private.write("ping")
                    lastPingTS = nowPingTS    
    
    def onexit():
        ret = client_private.close()
        Log("Close the connection!", ret)
    

auto client_private = 다이얼 (wss://ws.okx.com:8443/ws/v5/private);

json getLogin ((string pAccessKey, 문자열 pSecretKey, 문자열 pPassphrase) auto ts = std::to_string (유닉스) json 로그인 = R"({ 로그인 args: [{ apiKey: 비밀번호: , 시간표: 신호: {cH00ffff} }) "_json; login[args][0][apiKey] = pAccessKey; login[args][0][passphrase] = pPassphrase; 로그인[args][0][타임스테ంపు] = ts; login[args][0][sign] = exchange.HMAC ((sha256, base64, ts + GET + /users/self/verify, pSecretKey); 로그인 반환 ♪ ♪

공백 주식 (() { SetErrorFilter (실점 필터 설정) json posSubscribe = R"({ op: , 그스: [{ 채널: 위치, instType: ANY }] }) "_json;

auto accessKey = "xxx";
auto secretKey = "xxx";
auto passphrase = "xxx";

client_private.write(getLogin(accessKey, secretKey, passphrase).dump());
Sleep(3000);
client_private.write(posSubscribe.dump());  

if (client_private.Valid) {
    uint64_t lastPingTS = Unix() * 1000;    

    while (true) {
        auto buf = client_private.read(-1);
        if (buf != "") {
            Log(buf);
        }
        if (buf == "") {
            if (client_private.write(posSubscribe.dump()) == 0) {
                Log("Disconnection detected, connection closed, reconnect");
                client_private.close();
                client_private = Dial("wss://ws.okx.com:8443/ws/v5/private");
                client_private.write(getLogin(accessKey, secretKey, passphrase).dump());
                Sleep(3000);
                client_private.write(posSubscribe.dump());
            }
        }
        
        uint64_t nowPingTS = Unix() * 1000;
        if (nowPingTS - lastPingTS > 10 * 1000) {
            client_private.write("ping");
            lastPingTS = nowPingTS;
        }
    }
}

}

무효 한 출입자 클라이언트_프라이빗.클로즈 ((); 로그 (출출) }


#### HttpQuery(...)

```HttpQuery(Url, PostData, Cookies, Headers, IsReturnHeader)``` is an access of web URL. Parameter value: all are of string types.

Note:
* The ```HttpQuery(...)``` function only supports ```JavaScript``` language.
* For the ```Python``` language, you can use ```urllib``` to send http requests directly.

```HttpQuery(...)``` is mainly used to access the exchange interfaces that do not require signatures, such as public interfaces including market information.
An example of an API that does not require a signature to access OKX: the return value is a ```JSON``` string, which can be parsed by using the function ```JSON.parse()``` in JavaScript language strategies.

```js
function main(){
  // An example of GET access without parameters
  var info = JSON.parse(HttpQuery("https://www.okx.com/api/v5/public/time"))
  Log(info)
  // An example of GET access with parameters
  var ticker = JSON.parse(HttpQuery("https://www.okx.com/api/v5/market/books?instId=BTC-USDT"))
  Log(ticker)
}
import json
import urllib.request
def main():
    # HttpQuery does not support Python, you can use urllib/urllib2 instead
    info = json.loads(urllib.request.urlopen("https://www.okx.com/api/v5/public/time").read().decode('utf-8'))
    Log(info)
    ticker = json.loads(urllib.request.urlopen("https://www.okx.com/api/v5/market/books?instId=BTC-USDT").read().decode('utf-8'))
    Log(ticker)
void main() {
    auto info = json::parse(HttpQuery("https://www.okx.com/api/v5/public/time"));
    Log(info);
    auto ticker = json::parse(HttpQuery("https://www.okx.com/api/v5/market/books?instId=BTC-USDT"));
    Log(ticker);
}

URL의 반환 컨텐츠를 얻기 위해, 두 번째 매개 변수가PostData문자열 모양입니다.a=1&b=2&c=abc, 제출POST, 다른PUT;의 파라미터PostData{method:'PUT', data:'a=1&b=2&c=abc'}.

PostData매개 변수도 될 수 있습니다JSON string.

매개 변수의 형식Cookies이 경우:a=10; b=20; 각 매개 변수는 반점으로 구분됩니다.;- 그래요 매개 변수의 형식Headers이 경우:User-Agent: Mobile\nContent-Type: text/html; 각 매개 변수는 새 줄 문자로 구분됩니다.\n.

두 번째 매개 변수는PostData, 예를 들어, 사용자 정의 할 수 있습니다:HttpQuery("http://www.abc.com", {method:'PUT', data:'a=1&b=2&c=abc'}); 참고: 만약 당신이 시간 정지를 설정해야 한다면HttpQuery함수를 추가할 수 있습니다.timeout속성{method:'put',data:'a=1&B=2&C=ABC'}(전산 60초)

1초 타임아웃 설정:HttpQuery("http://www.abc.com", {method:'PUT', data:'a=1&b=2&c=abc', timeout:1000})

세 번째 매개 변수는 문자열을 전달하는 데 필요합니다.Cookie하지만POST두 번째 매개 변수를 null로 설정할 필요가 없습니다. 시뮬레이션 테스트 중에, URL을 시뮬레이션 할 수 없기 때문에 함수는 고정 문자열을 반환합니다.Dummy Data이 인터페이스를 사용하여 문자 메시지를 보내거나 다른 API 인터페이스와 상호 작용할 수 있습니다.

GET방법 호출 예제:HttpQuery("http://www.baidu.com"). POST방법 호출 예제:HttpQuery("http://www.163.com", "a=1&b=2&c=abc").

귀환의 호출 예제Header:

HttpQuery("http://www.baidu.com", null, "a=10; b=20", "User-Agent: Mobile\nContent-Type: text/html", true)  // will return {Header: HTTP Header, Body: HTML}
  • 기능HttpQuery프록시 설정을 사용합니다:

    function main() {
        // This time, set proxy and send http request; without username and password, this http request will be sent through the proxy
        HttpQuery("socks5://127.0.0.1:8889/http://www.baidu.com/")
    
        // Set the proxy and send http request this time, enter the user name and password, only the current call of HttpQuery takes effect, then call HttpQuery ("http://www.baidu.com") again so that the proxy will not be used
        HttpQuery("socks5://username:password@127.0.0.1:8889/http://www.baidu.com/")
    }
    
    # If HttpQuery does not support Python, you can use Python urllib2 library
    
    void main() {
        HttpQuery("socks5://127.0.0.1:8889/http://www.baidu.com/");
        HttpQuery("socks5://username:password@127.0.0.1:8889/http://www.baidu.com/");
    }
    
  • 기능HttpQuery비동기 버전입니다HttpQuery_Go: 사용 방법은 함수와 비슷합니다exchange.Go, 예를 들어 종합 시장 데이터를 얻기 위해 거래소의 공개 인터페이스에 비동기적으로 액세스합니다.

    function main() {
        // Set up the first asyncthread
        var r1 = HttpQuery_Go("https://www.okx.com/api/v5/market/tickers?instType=SPOT")
        // Set up the second asyncthread
        var r2 = HttpQuery_Go("https://api.huobi.pro/market/tickers")
        
        // Get the return value of the first asyncthread
        var tickers1 = r1.wait()
        // Get the return value of the second asyncthread
        var tickers2 = r2.wait()
        
        // Print result
        Log("tickers1:", tickers1)
        Log("tickers2:", tickers2)
    }
    
    # Not supported
    
    // Not supported
    
  • 함수의 사용HttpQuery(...)백테스트 시스템에서: 데이터를 이용해서 얻을 수 있습니다.HttpQuery(...)요청 (지원만)GET백테스트 시스템에서 20번의 제한이 적용됩니다.HttpQuery(...)접근은 데이터를 캐시할 것입니다.HttpQuery(...)동일한 URL에 두 번째 액세스에서 캐시 된 데이터를 반환합니다 (더 이상 실제 웹 요청이 없습니다).

    우리는 서버 또는 장치에서 서비스 프로그램을 실행할 수 있습니다.HttpQuery(...)전략 프로그램에서, 그리고 테스트를 위한 Go 언어의 서비스 프로그램은 다음과 같이 표시됩니다.

    package main
    import (
        "fmt"
        "net/http"
        "encoding/json"
    )
    
    func Handle (w http.ResponseWriter, r *http.Request) {
        defer func() {
            fmt.Println("req:", *r)
            ret := map[string]interface{}{
                "schema" : []string{"time","open","high","low","close","vol"},
                "data" : []interface{}{
                    []int64{1564315200000,9531300,9531300,9497060,9497060,787},
                    []int64{1564316100000,9495160,9495160,9474260,9489460,338},
                },
            }
            b, _ := json.Marshal(ret)
            w.Write(b)
        }()
    }
    
    func main () {
        fmt.Println("listen http://localhost:9090")
        http.HandleFunc("/data", Handle)
        http.ListenAndServe(":9090", nil)
    }
    

    함수를 사용HttpQuery(...)전략 백테스팅 중에 요청을 보내기 위해:

    function main() {
        // You can write the IP address of the device where the service program is run
        Log(HttpQuery("http://xxx.xx.x.xxx:9090/data?msg=hello"));
        Log(exchange.GetAccount());
    }
    
    # If HttpQuery does not support Python, you can use Python urllib2 library
    
    void main() {
        //  You can write the IP address of the device where the service program is run
        Log(HttpQuery("http://xxx.xx.x.xxx:9090/data?msg=hello"));
        Log(exchange.GetAccount());
    }
    

    img

    요청에서 응답 데이터의 트랜스코딩을 지원하고, 또한 일반적인 코딩을 지원합니다. 정해진PostData파라미터:{method: "GET", charset: "GB18030"}응답 데이터 트랜스코딩 (GB18030) 을 실현할 수 있습니다.

코드 ((...)

Encode(algo, inputFormat, outputFormat, data, keyFormat, key string), 함수는 전달된 매개 변수에 따라 데이터를 암호화하고 문자열 값을 반환합니다.

매개 변수algo은 암호화 계산에 사용되는 알고리즘으로, 다음과 같이 설정할 수 있습니다: raw (알고리즘이 없음), sign, signTx, md4, md5, sha256, sha512, sha1, keccak256, sha3.224, sha3.256, sha3.384, sha3.512, sha3.keccak256, sha3.keccak512, sha512.384, sha512.256, sha512.224, emd160, blake2rip2b.256, blake2b.512, blake2b.512, blake2s.1288, blake2s.256data처리해야 하는 데이터입니다.inputFormat/outputFormat/keyFormat매개 변수들은raw, hex, base64그리고string- 그래요 만약keyFormat매개 변수가 비어 있지 않은 경우key매개 변수는 암호화 (HMAC) 를 위해 사용 됩니다. 그렇지 않으면 기본key사용 됩니다.


더 많은